123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import LineHeatmap from "./lineHeatmap";
- import "nouislider";
- const template = `<div>
- <div class="line-heatmap-controls">
- <div id="line-heatmap-slider"></div>
- </div>
- <div id="line-heatmap-canvas">
- <div id="line-heatmap-view"></div>
- <div id="line-heatmap-tooltip"></div>
- </div>
- </div>
- `;
- const cursorDist = 10;
- const stateObject = {};
- let x1, y1, x2, y2;
- let firstClick = true;
- let div = null;
- let posLeft;
- let posTop;
- let yBottom;
- let xBottom;
- function init (elementId, logString, useTooltip = false, config = {}) {
- const el = document.getElementById(elementId);
- el.innerHTML = template;
- const logData = logTransform(logString);
- // create container
- const heatmap = new LineHeatmap('line-heatmap-view');
- heatmap.create(config);
- heatmap.setTrackData(logData);
- const html5Slider = document.getElementById('line-heatmap-slider');
- noUiSlider.create(html5Slider, {
- start: [1, logData.length],
- connect: true,
- step: 1,
- margin: 1,
- range: {
- 'min': 1,
- 'max': logData.length
- }
- });
-
- stateObject['container'] = el;
- stateObject['heatmap'] = heatmap;
- stateObject['data'] = logData;
- stateObject['slider'] = html5Slider;
- if (useTooltip) {
- registerClickEvent();
- const canvasWrapper = document.getElementById('line-heatmap-canvas');
- const tooltip = document.getElementById('line-heatmap-tooltip');
- function updateTooltip (x, y, value) {
- const transl = `translate(${x + cursorDist}px, ${y + cursorDist}px)`;
- tooltip.style.webkitTransform = transl;
- tooltip.innerHTML = `(${x},${y},${value})`;
- };
- canvasWrapper.onmousemove = function (ev) {
- var x = ev.layerX;
- var y = ev.layerY;
- // getValueAt gives us the value for a point p(x/y)
- var value = stateObject['heatmap'].instance.getValueAt({
- x: x,
- y: y
- });
- tooltip.style.display = 'block';
- updateTooltip(x, y, value);
- };
- // hide tooltip on mouseout
- canvasWrapper.onmouseout = function() {
- tooltip.style.display = 'none';
- };
- /* tooltip code end */
- }
- html5Slider.noUiSlider.on('update', function (values, handle) {
- const logValues = this.get();
- const newData = stateObject['data'].slice(+logValues[0]-1, +logValues[1] + 1);
- stateObject['heatmap'].setTrackData(newData);
- if(div !== null)
- updateDivText(div, posLeft, posTop, xBottom, yBottom);
- });
- }
- function updateLogString (logString) {
- const logData = logTransform(logString);
- stateObject['data'] = logData;
- stateObject['slider'].noUiSlider.updateOptions({
- range: {
- 'min': 1,
- 'max': logData.length
- }
- });
- stateObject['heatmap'].setTrackData(logData);
- }
- function countClicks (x1, y1, x2, y2) {
- const instance = stateObject['heatmap'].instance;
- const points = instance.getData().data;
- let counter = 0;
- for(let i = 0; i < points.length; ++i) {
- const point = points[i];
- if (point.x >= x1 && point.y >= y1) {
- if (point.x <= x2 && point.y <= y2) {
- counter += point.value;
- }
- }
- }
- return counter;
- }
- function getClicksInWindow (x1, y1, x2, y2) {
- const instance = stateObject['heatmap'].instance;
- const points = instance.getData().data;
- const list = [];
- for(let i = 0; i < points.length; ++i) {
- const point = points[i];
- if (point.x >= x1 && point.y >= y1) {
- if (point.x <= x2 && point.y <= y2) {
- list.push(point);
- }
- }
- }
- return list;
- }
- function totalClicks () {
- return stateObject['data'].length;
- }
- function getData () {
- return stateObject['data'];
- }
- function logTransform (logString) {
- const data = logString.split("\n")
- .filter(v => v.split(',').length > 3)
- .map(v => {
- const o = JSON.parse('[' + v + ']');
- return {
- x: o[0],
- y: o[1],
- value: 1
- };
- });
- return data;
- }
- function registerClickEvent () {
- const elemen = document.querySelector(".heatmap-canvas");
- window.onclick = function (evt) {
- if(evt.target !== elemen) {
- return;
- }
- if (firstClick) {
- if (evt.pageX || evt.pageY) {
- x1 = evt.pageX;
- y1 = evt.pageY;
- } else {
- x1 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
- y1 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
- }
- x1 -= elemen.offsetLeft;
- y1 -= elemen.offsetTop;
- firstClick = false;
- } else {
- if (evt.pageX || evt.pageY) {
- x2 = evt.pageX;
- y2 = evt.pageY;
- } else {
- x2 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
- y2 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
- }
- x2 -= elemen.offsetLeft;
- y2 -= elemen.offsetTop;
- firstClick = true;
- if (div !== null) {
- document.getElementById("line-heatmap-canvas").removeChild(div);
- div = null;
- }
- div = document.createElement("div");
- posLeft = Math.min(x1,x2);
- posTop = Math.min(y1,y2) - 585;
- yBottom = Math.max(y1,y2) - 585;
- xBottom = Math.max(x1,x2);
- const width = Math.abs(xBottom - posLeft);
- const height = Math.abs(yBottom - posTop);
- updateDivText(div, posLeft, posTop, xBottom, yBottom);
- div.style.width = width + "px";
- div.style.height = height + "px";
- div.style.position = "absolute";
- div.style.top = posTop + "px";
- div.style.left = posLeft + "px";
- div.style.border = "1px solid green";
- document.getElementById("line-heatmap-canvas").append(div);
-
- }
- }
- }
- function updateDivText (div, posLeft, posTop, xBottom, yBottom) {
- const count = countClicks(posLeft, posTop, xBottom, yBottom);
- const ratio = count/totalClicks();
- div.innerHTML = `<span style="font-size:14px">Quantidade de clicks: ${count}</span>
- <span style="font-size:14px">Proporção em relação ao total: ${ratio}</span>`;
- }
- function clicksEuclideanDist (points) {
- if(points.length <= 1) {
- return 0;
- } else if (points.length == 2) {
- const p1 = points[0];
- const p2 = points[1];
- return euclideanDist(p1, p2);
- } else {
- let count = 0;
- points.reduce((p1, p2) => {
- count += euclideanDist(p1, p2);
- return p2;
- });
- return count;
- }
- }
- function calcPixelsPerClick () {
- const data = getData();
- const totalPixels = clicksEuclideanDist(data);
- return totalPixels / totalClicks();
- }
- function calcPixelsPerClickInArea () {
- if(div == null) {
- return 0;
- }
- const data = getClicksInWindow(posLeft, posTop, xBottom, yBottom);
- const totalPixels = clicksEuclideanDist(data);
- return totalPixels / countClicks(posLeft, posTop, xBottom, yBottom);
- }
- function euclideanDist (p1, p2) {
- return Math.sqrt(Math.pow(p1.x-p2.x, 2) + Math.pow(p1.y-p2.y, 2));
- }
- export default {
- init,
- updateLogString,
- countClicks,
- totalClicks,
- getData,
- calcPixelsPerClick,
- calcPixelsPerClickInArea
- }
|