I’m creating a drawing of a layout with the canvas and fabric.js library and in the same div I create a heatmap with the help of the heatmap.js library here. The problem is that when creating the heatmap, the mouse up, down and canvas wheel functionality stops working. Does anyone have an idea how to solve this or any other suggestions?
Currently my code looks like this:
<template>
<section>
<h1 class="title">Mapa de Calor do Centro de DistribuiĆ§Ć£o</h1>
<div class="box">
<div class="heatmap-canvas">
<canvas id="mycanvas"></canvas>
</div>
</div>
</section>
</template>
.box {
height: 100%;
width: auto;
}
.heatmap-canvas {
overflow: hidden;
margin: auto;
width: auto;
height: 830px;
}
<script>
import { fabric } from "fabric";
import axios from "axios";
import h337 from "heatmapjs";
export default {
layout: "collection_layout",
data() {
return {
panning: false,
data: {
pallets: [],
rulers: []
},
numbers: [],
configs: {
scale_factor: 18,
font_size: 4,
map_height: 50, // In meters
map_width: 224 // In meters
}
};
},
mounted() {
axios
.get("/layoutCD.json")
.then(response => {
this.data.pallets = response.data.pallets;
this.data.rulers = response.data.rulers;
this.create_renderize(response.data);
})
.catch(error => {
console.log(error);
});
axios
.get("/array_endereco.json")
.then(response => {
this.numbers = response.data;
this.create_renderize_heat(this.numbers, this.data);
})
.catch(error => {
console.log(error);
});
},
methods: {
create_renderize(data) {
// Create the canvas
var canvas = new fabric.Canvas("mycanvas", { isDrawingMode: false });
fabric.Object.prototype.objectCaching = false; // Avoids blurry text
fabric.Object.prototype.selectable = false;
// Set the width and height of the map canvas
canvas.setWidth(this.scale(this.configs.map_width));
canvas.setHeight(this.scale(this.configs.map_height));
//Mouse press event
canvas.on("mouse:down", function(e) {
this.panning = true;
canvas.selection = false;
});
//Mouse up event
canvas.on("mouse:up", function(e) {
this.panning = false;
canvas.selection = true;
});
// Move the canvas event
canvas.on("mouse:move", function(e) {
if (this.panning && e && e.e) {
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
}
});
canvas.on("mouse:wheel", function(e) {
var delta = e.e.deltaY;
var zoom = canvas.getZoom();
zoom *= 0.999 ** delta;
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
canvas.zoomToPoint({ x: e.e.offsetX, y: e.e.offsetY }, zoom);
e.e.preventDefault();
e.e.stopPropagation();
});
// Draw the distribution center map
this.renderMap(data, canvas);
},
/* FUNCTION renderMap
Renders the distribution center map
*/
renderMap(data, canvas) {
// Draw the pallets
for (let i = 0; i < data.pallets.length; i++) {
let pallet = data.pallets[i];
this.drawPallet(pallet, canvas);
}
// Draw the rulers
for (let i = 0; i < data.rulers.length; i++) {
let ruler = data.rulers[i];
this.drawRuler(ruler, canvas);
}
},
/* FUNCTION drawRule
Draws a single ruler
*/
drawRuler(ruler, canvas) {
// Find out how the ticks and the label should be aligned
let align_tick_x = 0;
let align_tick_y = 0;
let left_label = scale(ruler.x_from + (ruler.x_to - ruler.x_from) / 2.0);
let top_label = scale(ruler.y_from);
let align_label_x = "center";
let align_label_y = "center";
let color = "#000";
// Horizontal rule pointed up
if (ruler.x_from < ruler.x_to) {
align_tick_y -= 8;
top_label += 10;
}
// Horizontal rule pointed down
else if (ruler.x_from > ruler.x_to) {
align_tick_y += 8;
top_label -= 10;
}
// Vertical rule pointed left
if (ruler.y_from < ruler.y_to) {
align_tick_x -= 8;
left_label += 8;
top_label += scale((ruler.y_to - ruler.y_from) / 2.0);
align_label_x = "left";
}
// Vertical rule pointed right
else if (ruler.y_from > ruler.y_to) {
align_tick_x += 8;
left_label -= 8;
top_label += scale((ruler.y_to - ruler.y_from) / 2.0);
align_label_x = "right";
}
// Check if a color has been specified for the ruler
if (typeof ruler.color != undefined) color = ruler.color;
// Create the rule
let ruler_main = new fabric.Line(
[
scale(ruler.x_from),
scale(ruler.y_from),
scale(ruler.x_to),
scale(ruler.y_to)
],
{ stroke: color }
);
let ruler_tick_l = new fabric.Line(
[
scale(ruler.x_from) + align_tick_x,
scale(ruler.y_from) + align_tick_y,
scale(ruler.x_from),
scale(ruler.y_from)
],
{ stroke: color }
);
let ruler_tick_r = new fabric.Line(
[
scale(ruler.x_to) + align_tick_x,
scale(ruler.y_to) + align_tick_y,
scale(ruler.x_to),
scale(ruler.y_to)
],
{ stroke: color }
);
let label = new fabric.Text(ruler.label, {
originX: align_label_x,
originY: align_label_y,
left: left_label,
top: top_label,
fontSize: configs.font_size,
fill: color
});
// Add to the canvas
canvas.add(ruler_main, ruler_tick_l, ruler_tick_r, label);
},
/* FUNCTION drawPallet
Draws a single pallet
*/
drawPallet(pallet, canvas) {
let bg_color =
typeof pallet.bg_color == "undefined" ? false : pallet.bg_color;
let border_color =
typeof pallet.border_color == "undefined"
? "#000"
: pallet.border_color;
let label_color =
typeof pallet.label_color == "undefined" ? "#000" : pallet.label_color;
let has_label = typeof pallet.label == "undefined" ? false : true;
// Create the objects
if (has_label) {
let pallet_obj = new fabric.Rect({
width: this.scale(pallet.width),
height: this.scale(pallet.height),
fill: bg_color,
stroke: border_color
});
let label_obj = new fabric.Text(pallet.label, {
originX: "center",
originY: "center",
left: this.scale(0.5 * pallet.width),
top: this.scale(0.5 * pallet.height),
fontSize: this.configs.font_size
});
// Create the group
let group = new fabric.Group([pallet_obj, label_obj], {
left: this.scale(pallet.x),
top: this.scale(pallet.y),
fill: label_color
});
// Add to the canvas
canvas.add(group);
} else {
let pallet_obj = new fabric.Rect({
width: this.scale(pallet.width),
height: this.scale(pallet.height),
left: this.scale(pallet.x),
top: this.scale(pallet.y),
fill: bg_color,
stroke: border_color
});
// Add to the canvas
canvas.add(pallet_obj);
}
},
create_renderize_heat(numbers, layout) {
// minimal heatmap instance configuration
var heatmapInstance = h337.create({
container: document.querySelector(".heatmap-canvas"),
radius: 18,
scaleRadius: true,
});
// now generate some random data
var points = [];
var arr = {
keys: Object.keys(numbers),
values: Object.values(numbers)
};
var max = 0;
var i, j, flag = 0, pos = 0;
for (i = 0; i < arr.keys.length; i++) {
for (j = 0; j < layout.pallets.length; j++) {
let str = layout.pallets[j].label.slice(0, 11);
if (str == arr.keys[i]) {
flag = 1;
pos = j;
break;
}
str = layout.pallets[j].label.slice(13, 24);
if (str == arr.keys[i]) {
flag = 1;
pos = j;
break;
}
str = layout.pallets[j].label.slice(26, 37);
if (str == arr.keys[i]) {
flag = 1;
pos = j;
break;
}
}
if (flag == 1) {
var val = arr.values[i];
max = Math.max(max, val);
var point = {
x: Math.floor(
this.scale(layout.pallets[pos].width / 2 + layout.pallets[pos].x)
),
y: Math.floor(
this.scale(layout.pallets[pos].height / 2 + layout.pallets[pos].y)
),
value: val
};
points.push(point);
}
flag = 0;
}
// heatmap data format
var data = {
max: max,
data: points
};
// if you have a set of datapoints always use setData instead of addData
// for data initialization
heatmapInstance.setData(data);
},
/* FUNCTION scale
Scale the given value to convert metric units to pixels in the canvas according to
the scale_factor defined in the configurations
*/
scale(value) {
return value * this.configs.scale_factor;
}
}
};
</script>