JSFiddle:https://jsfiddle.net/bd7kc24a/20/
一位同事和我尝试使用画布时遇到了障碍,我们希望在画布上有一个Rect作为实际的工作区域。我们正在尝试向该Rect添加网格和/或点背景,但我们需要该部分在缩放发生时不进行缩放。如果有一种简单的方法可以做到这一点,我们很乐意了解它,但这就是我们目前所处的位置。
上面的示例jsfiddle有点做我们需要它做的事情。但我们遇到了问题:
所以我正在尝试创建一个自定义子类,以便在序列化时重新应用静态画布背景,但是一旦我添加了这个基类,它将不再执行loadFromJSON调用或点击回调。
任何帮助将不胜感激!特别是如果有一种简单的方法可以做到这一点,我们只是错过了文档。
JSFiddle:https://jsfiddle.net/bd7kc24a/20/
'use strict';
debugger;
fabric.CanvasMap = fabric.util.createClass(fabric.Rect, {
type: 'canvasMap',
initialize: function(element, options) {
this.callSuper('initialize', element, options);
options && this.set('name', options.name);
options && this.set('imageRef', options.imageRef);
this.rescaleBackground(10);
},
rescaleBackground: function(scale) {
const padding = 0;
this.imageRef.scaleToWidth(scale);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(this.imageRef);
patternSourceCanvas.setDimensions({
width: this.imageRef.getWidth() + padding,
height: this.imageRef.getHeight() + padding
});
let pattern = new fabric.Pattern({
source: patternSourceCanvas.getElement(),
repeat: 'repeat'
});
this.setPatternFill(pattern);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
name: this.name
});
}
});
fabric.CanvasMap.fromObject = function (object, callback) {
var _enlivenedObjects;
object.imageRef = squareImg;
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
delete object.objects;
_enlivenedObjects = enlivenedObjects;
});
const newCanvasMap = new fabric.CanvasMap(_enlivenedObjects, object);
return newCanvasMap;
};
let floorPlan = new fabric.Canvas('floorPlan', {
hoverCursor: 'pointer',
backgroundColor: '#cccccc'
});
function reloadFromJSON() {
let jsonMap = floorPlan.toJSON();
let jsonMapString = JSON.stringify(jsonMap);
floorPlan.loadFromJSON(jsonMapString, function() {
floorPlan.renderAll();
});
}
//let mapBackground = new fabric.Canvas();
function addShape() {
let coordinates = floorPlan.getVpCenter();
const circle = new fabric.Circle({
name: 'some circle',
radius: 20,
fill: 'blue',
left: coordinates.x - 20,
top: coordinates.y - 20
});
floorPlan.add(circle);
}
let defaultScale = 10;
let squareSVG = '<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><g> <title>background</title><rect fill="#fff" id="canvas_background" height="12" width="12" y="-1" x="-1"/></g><g> <title>Layer 1</title> <rect id="svg_1" height="9.87496" width="9.99996" y="0.062519" x="0.031269" stroke-width="1.5" stroke="#000000" fill="none"/> </g></svg>'
let squareImg;
fabric.loadSVGFromString(squareSVG, function(objects, options) {
squareImg = fabric.util.groupSVGElements(objects, options);
const map = new fabric.CanvasMap({
imageRef: squareImg,
height: 300, width: 300,
left: 20, top: 20,
strokeWidth: 2,
stroke: 'red',
selectable: false,
evented: false, hasBorders: true, hasControls: false
});
floorPlan.add(map);
floorPlan.renderAll();
});
function setBackground(scale) {
floorPlan._objects[0].rescaleBackground(scale);
}
//logic for binding objects to MAP
floorPlan.observe('object:moving', function(e) {
let obj = e.target;
if (obj.getHeight() > map.height || obj.getWidth() > map.width) {
obj.setScaleY(obj.originalState.scaleY);
obj.setScaleX(obj.originalState.scaleX);
}
obj.setCoords();
if (obj.top - (obj.cornerSize / 2) < map.top ||
obj.left - (obj.cornerSize / 2) < map.left) {
console.log(map.top, map.left);
obj.top = Math.max(obj.top, obj.top - obj.top + (obj.cornerSize / 2) + map.top);
obj.left = Math.max(obj.left, obj.left - obj.left + (obj.cornerSize / 2) + map.left);
}
if (obj.top + obj.height + obj.cornerSize > map.height ||
obj.left + obj.width + obj.cornerSize > map.width) {
obj.top = Math.min(obj.top, (map.height + map.top) - obj.height + obj.top - obj.top - obj.cornerSize / 2);
obj.left = Math.min(obj.left, (map.width + map.left) - obj.width + obj.left - obj.left - obj.cornerSize / 2);
}
});
//zoom
let clicks = 0;
floorPlan.on('mouse:down', function(event) {
clicks += 1;
setTimeout(function() {
if (clicks > 1) {
console.log(event.e.clientX);
floorPlan.zoomToPoint(new fabric.Point(event.e.clientX, event.e.clientY), floorPlan.getZoom() + 1);
}
clicks = 0;
}, 300);
});
function zoomIn() {
floorPlan.setZoom(floorPlan.getZoom() + 0.5);
console.log(floorPlan.getZoom(), defaultScale * floorPlan.getZoom());
setBackground(defaultScale / floorPlan.getZoom());
floorPlan.renderAll();
}
function zoomOut() {
floorPlan.setZoom(floorPlan.getZoom() - 0.5); ;
console.log(floorPlan.getZoom(), defaultScale * floorPlan.getZoom());
setBackground(defaultScale / floorPlan.getZoom());
floorPlan.renderAll();
}
function renderAll() {
floorPlan.renderAll();
}
//pan
function pan(event) {
event.e.preventDefault();
let panAmount = {
x: event.e.deltaX,
y: event.e.deltaY
};
//logic for binding the map to the screen during pan
/*
* We need to use the following points and check for negative or overflow values
* canvas.oCoords.tl - top left
* canvas.oCoords.bl - bottom left
* canvas.oCoords.tr - top right
* canvas.oCoords.br - bottom right
*/
//pan left
if (panAmount.x > 0) {
if (map.oCoords.tr.x < floorPlan.width - 40) {
panAmount.x = 0;
}
}
//pan right
if (panAmount.x < 0) {
if (map.oCoords.tl.x > 40) {
panAmount.x = 0;
}
}
//pan up
if (panAmount.y > 0) {
if (map.oCoords.bl.y < floorPlan.height - 40) {
panAmount.y = 0;
}
}
//pan down
if (panAmount.y < 0) {
if (map.oCoords.tl.y > 40) {
panAmount.y = 0;
}
}
// assuming the logic above allows the scroll, get the relative scroll values and create a new fabric point and then scroll to it
const delta = new fabric.Point(-panAmount.x, -panAmount.y);
floorPlan.relativePan(delta);
}
floorPlan.on('mouse:wheel', pan);