我正在尝试制作可以调整大小的绘图画布。 我找到了一种方法,但每次更新画布时都会删除绘图,不幸的是它有一个奇怪的“bug”。 在Firefox中,一切都按预期工作,但是当我在Chrome中尝试时,我无法调整画布大小。
如果它不是最漂亮或最有效的代码我很抱歉。
$(document).ready(function() {
$("#canvaSizer").mouseup(function() {
canvaWidthNew = document.getElementById('canvaSizer').clientWidth;
if (canvaWidthNew != canvaWidth) {
initialize();
}
canvaWidth = canvaWidthNew;
});
canvaWidth = document.getElementById('canvaSizer').clientWidth;
var myscreen = document.getElementById("screen");
var ctx = myscreen.getContext("2d");
initialize();
function initialize() {
// Fill Window Width and Height
myscreen.width = document.getElementById('canvaSizer').clientWidth;
myscreen.height = document.getElementById('canvaSizer').clientHeight;
// Set Background Color
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, myscreen.width, myscreen.height);
// Mouse Event Handlers
if (myscreen) {
var isDown = false;
var canvasX, canvasY;
ctx.lineWidth = 5;
$(myscreen)
.mousedown(function(e) {
isDown = true;
ctx.beginPath();
canvasX = e.pageX - myscreen.offsetLeft;
canvasY = e.pageY - myscreen.offsetTop;
ctx.moveTo(canvasX, canvasY);
})
.mousemove(function(e) {
if (isDown !== false) {
canvasX = e.pageX - myscreen.offsetLeft;
canvasY = e.pageY - myscreen.offsetTop;
ctx.lineTo(canvasX, canvasY);
ctx.strokeStyle = "#000";
ctx.stroke();
}
})
.mouseup(function(e) {
isDown = false;
ctx.closePath();
});
}
// Touch Events Handlers
draw = {
started: false,
start: function(evt) {
ctx.beginPath();
ctx.moveTo(
evt.touches[0].pageX,
evt.touches[0].pageY
);
this.started = true;
},
move: function(evt) {
if (this.started) {
ctx.lineTo(
evt.touches[0].pageX,
evt.touches[0].pageY
);
ctx.strokeStyle = "#000";
ctx.lineWidth = 5;
ctx.stroke();
}
},
end: function(evt) {
this.started = false;
}
};
// Touch Events
myscreen.addEventListener('touchstart', draw.start, false);
myscreen.addEventListener('touchend', draw.end, false);
myscreen.addEventListener('touchmove', draw.move, false);
// Disable Page Move
document.body.addEventListener('touchmove', function(evt) {
evt.preventDefault();
}, false);
}
});
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#canvasWrapper {
width: 95.6%;
height: 100%;
position: absolute;
z-index: 1;
overflow: hidden;
}
#canvaSizer {
padding: 0;
display: block;
width: 35%;
border-style: solid;
height: 35%;
position: absolute;
resize: both;
max-width: 95%;
min-width: 35%;
max-height: 95%;
min-height: 35%;
overflow: hidden;
resize: both;
}
canvas {}
#screen {
cursor: crosshair;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<body>
<div id="canvasWrapper">
<div id="canvaSizer">
<canvas id="screen"></canvas>
</div>
</div>
</body>
</html>
答案 0 :(得分:0)
Chrome有关resize
CSS元素的错误。 (Filed a bug here)
如果您放置一个孩子img
,则调整大小处理程序将不可见,但它会调整大小!
这同样适用于canvas
(或input
)。处理程序是阴影和反应迟钝。
解决方案是添加一个自定义的“角落”处理程序元素(具有足够的JS和事件侦听器)...
同时,这里对您的代码进行了一些改进:
// (i) P.S: i filed a bug here: https://bugs.webkit.org/show_bug.cgi?id=181818
jQuery(function($) { // (i) Better DOM ready
var canvaSizer = document.getElementById("canvaSizer");
var $canvaSizer = $(canvaSizer);
var canvaWidth = $canvaSizer.width();
var canvas = document.getElementById("screen");
var ctx = canvas.getContext("2d");
var $canvas = $(canvas);
var lineWidth = 5; // (i)
var color = "#000"; // (i)
// Events Handlers
// (i) this object is all you need. Don't make other handlers
var draw = {
started: false,
// (i) you need this function because you want to paint also on mousedown
paint: function(e) {
// (i) instead of wrapping large chunks of code, use return
if (!draw.started) return;
// (i) Don't duplicate event handlers, rather figure if a certain event exists
e = e.touches ? e.touches[0] : e;
ctx.lineTo(
e.pageX - canvas.offsetLeft - (lineWidth / 2), // (i) forgot about lineWidth?
e.pageY - canvas.offsetTop - (lineWidth / 2)
);
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round'; // (i) why not, will paint a mousedown shape
ctx.stroke();
},
start: function(e) {
ctx.beginPath();
// (i) No need to ctx.moveTo
// (i) `this` is now `$canvas` so use `draw`
draw.started = true;
draw.paint(e);
},
move: function(e) {
draw.paint(e);
},
end: function() {
draw.started = false;
ctx.closePath(); // (i) You forgot this one
}
};
function initialize() {
// Fill Window Width and Height
canvas.width = canvaSizer.clientWidth;
canvas.height = canvaSizer.clientHeight;
// Set Background Color
ctx.fillStyle = "#fff";
// (i) This causes your canvas to clear on eveery initialize()
// and you're calling initialize() on wrapper resize!
ctx.fillRect(0, 0, canvas.width, canvas.height);
// (i) No need to define ctx styles, you already have them in draw.move
// Attach events
// (i) Use a `.draw` namespace, so you can clear easily all events using .off()
// (i) On init - off all events in the ".draw" namespace (if any)
// (i) Use jQuery and pass the needed events
// (i) You want to attach event handlers only once, not on every initialize()
$canvas.off('.draw').on({
'touchstart.draw mousedown.draw': draw.start,
'touchmove.draw mousemove.draw': draw.move,
});
// (i) end should be delegated to body
// you could mouseup over body, not necessarily over the paint area
// Disable Page Move (i) if we're operating over $canvaSizer!!
$('body').off('.draw').on({
'touchmove.draw': function(evt) {
if (draw.started) evt.preventDefault();
},
'mouseup.draw': function() {
draw.end();
}
});
}
// Wrapper resize event // (i) comment what does this - it helps.
// (i) Don't use mouseup! Mouseup happens even if you're painting. Use "resize"
$canvaSizer.on('resize', function() {
var canvaWidthNew = $(this).width();
if (canvaWidthNew != canvaWidth) {
canvaWidth = canvaWidthNew; // (i) move this inside, before init
initialize();
}
});
// INIT!
initialize();
});
* {
margin: 0;
}
html,
body {
height: 100%;
font: 14px/1.4 sans-serif;
}
#canvaSizer {
padding: 0;
display: inline-block;
width: 35%;
border-style: solid;
height: 35%;
position: absolute;
resize: both;
max-width: 95%;
min-width: 35%;
max-height: 95%;
min-height: 35%;
overflow: hidden;
/*resize: both; so... don't... or figure out a JS way to do it. */
}
#screen {
display: inline-block;
cursor: crosshair;
position: relative;
}
<div id="canvaSizer">
<canvas id="screen"></canvas>
</div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>