如何解决如何限制HTML5画布缩放功能
我有一个画布,它的左下绿色边框用于将来的图表,橙色框用于显示更多示例
var HiDPICanvas = function(container_id,color,w,h) {
/*
objects are objects on the canvas,first elements of dictionary are background elements,last are on the foreground
canvas will be placed in the container
canvas will have width w and height h
*/
var objects = {
box : [],borders : []
}
var doNotMove = ['borders']
var scale = {
min : -3,max : 27,current : 0,sharpness : 0.05
}
// is mouse down & its coords
var mouseDown = false
var lastX = window.innerWidth/2
var lastY = window.innerHeight/2
// return pixel ratio
var getRatio = function() {
var ctx = document.createElement("canvas").getContext("2d");
var dpr = window.devicePixelRatio || 1;
var bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
}
// return high dots per inch canvas
var createHiDPICanvas = function() {
var ratio = getRatio();
var chart_container = document.getElementById(container_id);
var can = document.createElement("canvas");
can.style.backgroundColor = color
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio,ratio,0);
chart_container.appendChild(can);
return can;
}
// add object to the canvas
var add = function(object,category) {
objects[category].push(object)
}
// clear canvas
var clearCanvas = function(x0,y0,x1,y1) {
ctx.clearRect(x0,y1);
ctx.beginPath();
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 1;
ctx.closePath();
}
// check function do I can move this group of objects
var canMove = function(groupname) {
for (var i = 0; i < doNotMove.length; i++) {
var restricted = doNotMove[i]
if (restricted == groupname) {
return false
}
}
return true
}
// refresh all objects on the canvas
var refresh = function() {
clearCanvas(0,h)
var object // DO NOT REDRAW AS I NEED
for (var key in objects) {
for (var i = 0; i < objects[key].length; i++) {
object = objects[key][i]
object.refresh()
}
}
}
// shift all objects on the canvas except left and down borders and its content
var shiftObjects = function(event) {
event.preventDefault()
// track mouse coords
lastX = event.offsetX || (event.pageX - canvas.offsetLeft);
lastY = event.offsetY || (event.pageY - canvas.offsetTop);
// if mouse clicked now -> we can move canvas view left\right
if (mouseDown) {
var object
for (var key in objects) {
if (canMove(key)) {
for (var i = 0; i < objects[key].length; i++) {
object = objects[key][i]
object.move(event.movementX)
}
}
}
cci.refresh()
}
}
// transfer x to canvas drawing zone x coord (for not drawing on borders of the canvas)
var transferX = function(x) {
return objects.borders[0].width + x
}
var transferCoords = function(x,y) {
// no need to transfer y because borders are only at the left
return {
x : transferX(x),y : y
}
}
// change mouse state on the opposite
var toggleMouseState = function() {
mouseDown = !mouseDown
}
// make mouseDown = false,(bug removal function when mouse down & leaving the canvas)
var refreshMouseState = function() {
mouseDown = false
}
// print information about all objects on the canvas
var print = function() {
var groupLogged = true
console.log("Objects on the canvas:")
for (var key in objects) {
groupLogged = !groupLogged
if (!groupLogged) {console.log(key,":"); groupLogged = !groupLogged}
for (var i = 0 ; i < objects[key].length; i++) {
console.log(objects[key][i])
}
}
}
// Adds ctx.getTransform() - returns an SVGMatrix
// Adds ctx.transformedPoint(x,y) - returns an SVGPoint
var trackTransforms = function(ctx){
var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
var xform = svg.createSVGMatrix();
ctx.getTransform = function(){ return xform; };
var savedTransforms = [];
var save = ctx.save;
ctx.save = function(){
savedTransforms.push(xform.translate(0,0));
return save.call(ctx);
};
var restore = ctx.restore;
ctx.restore = function(){
xform = savedTransforms.pop();
return restore.call(ctx);
};
var scale = ctx.scale;
ctx.scale = function(sx,sy){
xform = xform.scaleNonUniform(sx,sy);
return scale.call(ctx,sx,sy);
};
var rotate = ctx.rotate;
ctx.rotate = function(radians){
xform = xform.rotate(radians*180/Math.PI);
return rotate.call(ctx,radians);
};
var translate = ctx.translate;
ctx.translate = function(dx,dy){
xform = xform.translate(dx,dy);
return translate.call(ctx,dx,dy);
};
var transform = ctx.transform;
ctx.transform = function(a,b,c,d,e,f){
var m2 = svg.createSVGMatrix();
m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
xform = xform.multiply(m2);
return transform.call(ctx,a,f);
};
var setTransform = ctx.setTransform;
ctx.setTransform = function(a,f){
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return setTransform.call(ctx,f);
};
var pt = svg.createSVGPoint();
ctx.transformedPoint = function(x,y){
pt.x=x; pt.y=y;
return pt.matrixTransform(xform.inverse());
}
}
var zoom = function(clicks){
var pt = ctx.transformedPoint(lastX,lastY);
ctx.translate(pt.x,pt.y);
var factor = Math.pow(1.1,clicks);
ctx.scale(factor,factor);
ctx.translate(-pt.x,-pt.y);
refresh()
}
var handleScroll = function(evt){
var delta = evt.wheelDelta ? evt.wheelDelta/40 : evt.detail ? -evt.detail : 0;
var changed = false
if (delta) {
scale.current += delta
// balance scale if it is out of bounds
if (scale.current >= scale.max) {
scale.current = scale.max - 3
changed = true
}
else if (scale.current <= scale.min) {
scale.current = scale.min + 3
changed = true
}
if (changed) {
delta = 0
}
zoom(delta)
//console.log("scale",scale.current)
}
return evt.preventDefault() && false;
};
// create canvas
var canvas = createHiDPICanvas()
var ctx = canvas.getContext("2d")
console.log("scale",scale.current)
trackTransforms(ctx)
// add event listeners to the canvas
// for scale changing
canvas.onmousewheel = handleScroll
// for moving canvas left and right
canvas.addEventListener("mousemove",shiftObjects )
canvas.addEventListener("mousedown",() => { toggleMouseState () })
canvas.addEventListener("mouseup",() => { toggleMouseState () })
canvas.addEventListener("mouseleave",() => { refreshMouseState() })
canvas.addEventListener("mouseenter",() => { refreshMouseState() })
return {
canvas : canvas,ctx : ctx,width : w,height : h,color : color,scale : scale,add : add,print : print,refresh: refresh
}
}
// cci -> canvas ctx info (dict)
var cci = HiDPICanvas("lifespanChart","#EDF7EE",780,640)
var ctx = cci.ctx
var canvas = cci.canvas
var Borders = function(width,color) {
var canvasWidth = cci.width
var canvasHeight = cci.height
var create = function() {
ctx.save();
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.lineWidth = 0.001;
ctx.fillStyle = color;
ctx.moveTo(0,0);
ctx.lineTo(width,0)
ctx.lineTo(width,canvasHeight-width)
ctx.lineTo(canvasWidth,canvasHeight)
ctx.lineTo(0,0)
ctx.stroke();
ctx.closePath();
ctx.fill();
ctx.restore()
}
create()
return {
refresh : create,width : width,color : color
}
}
var Box = function(x,y,color) {
var create = function() {
// if variables of the object does not exist - create them
if (this.x === undefined) {
this.x = x
this.y = y
this.width = a
this.color = color
}
ctx.save();
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.lineWidth = 0.001;
ctx.fillStyle = this.color;
ctx.moveTo(this.x,this.y);
ctx.lineTo(this.x + this.width,this.y)
ctx.lineTo(this.x + this.width,this.y + this.width)
ctx.lineTo(this.x,this.y)
ctx.stroke();
ctx.closePath();
ctx.fill();
ctx.restore()
}
var move = function(x_delta) {
this.x += x_delta
}
create()
return {
refresh : create,x : x,y : y,width : a,color : color,move : move
}
}
var borders = Borders(70,"#C7D8C7")
var box = new Box(150,150,50,"orange")
cci.add(box,'box')
cci.add(borders,'borders')
<div>
<div id="lifespanChart"></div>
</div>
但是我希望此画布具有2个限制,并且不知道如何实现。
- 限制。当我缩放时,对象不应该越过画布的边缘(不要左右移动鼠标)
- 限制。我希望这个绿色边框不会与画布上的所有其他对象成比例,并且始终保持在其位置上
我该如何实现?
谢谢
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。