【发布时间】:2010-08-06 04:21:30
【问题描述】:
有没有什么简单的方法可以放大和缩小画布(JavaScript)?基本上我有一个 400x400px 的画布,我希望能够使用“mousedown”(2x)放大并使用“mouseup”返回。
过去两天用谷歌搜索,但到目前为止没有运气。 :(
【问题讨论】:
标签: javascript canvas
有没有什么简单的方法可以放大和缩小画布(JavaScript)?基本上我有一个 400x400px 的画布,我希望能够使用“mousedown”(2x)放大并使用“mouseup”返回。
过去两天用谷歌搜索,但到目前为止没有运气。 :(
【问题讨论】:
标签: javascript canvas
根据使用 drawImage 的建议,您还可以将其与缩放功能结合使用。
因此,在您绘制图像之前,将上下文缩放到您想要的缩放级别:
ctx.scale(2, 2) // Doubles size of anything draw to canvas.
我在这里创建了一个小示例http://jsfiddle.net/mBzVR/4/,它使用 drawImage 和 scale 来放大 mousedown 和缩小 mouseup。
【讨论】:
试试这个:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<style>
body {
margin: 0px;
padding: 0px;
}
#wrapper {
position: relative;
border: 1px solid #9C9898;
width: 578px;
height: 200px;
}
#buttonWrapper {
position: absolute;
width: 30px;
top: 2px;
right: 2px;
}
input[type="button"] {
padding: 5px;
width: 30px;
margin: 0px 0px 2px 0px;
}
</style>
<script>
function draw(scale, translatePos) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.translate(translatePos.x, translatePos.y);
context.scale(scale, scale);
context.beginPath(); // begin custom shape
context.moveTo(-119, -20);
context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
context.bezierCurveTo(131, 50, 131, 20, 101, 0);
context.bezierCurveTo(141, -60, 81, -70, 51, -50);
context.bezierCurveTo(31, -95, -39, -80, -39, -50);
context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
context.closePath(); // complete custom shape
var grd = context.createLinearGradient(-59, -100, 81, 100);
grd.addColorStop(0, "#8ED6FF"); // light blue
grd.addColorStop(1, "#004CB3"); // dark blue
context.fillStyle = grd;
context.fill();
context.lineWidth = 5;
context.strokeStyle = "#0000ff";
context.stroke();
context.restore();
}
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var translatePos = {
x: canvas.width / 2,
y: canvas.height / 2
};
var scale = 1.0;
var scaleMultiplier = 0.8;
var startDragOffset = {};
var mouseDown = false;
// add button event listeners
document.getElementById("plus").addEventListener("click", function() {
scale /= scaleMultiplier;
draw(scale, translatePos);
}, false);
document.getElementById("minus").addEventListener("click", function() {
scale *= scaleMultiplier;
draw(scale, translatePos);
}, false);
// add event listeners to handle screen drag
canvas.addEventListener("mousedown", function(evt) {
mouseDown = true;
startDragOffset.x = evt.clientX - translatePos.x;
startDragOffset.y = evt.clientY - translatePos.y;
});
canvas.addEventListener("mouseup", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseover", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseout", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mousemove", function(evt) {
if (mouseDown) {
translatePos.x = evt.clientX - startDragOffset.x;
translatePos.y = evt.clientY - startDragOffset.y;
draw(scale, translatePos);
}
});
draw(scale, translatePos);
};
jQuery(document).ready(function() {
$("#wrapper").mouseover(function(e) {
$('#status').html(e.pageX + ', ' + e.pageY);
});
})
</script>
</head>
<body onmousedown="return false;">
<div id="wrapper">
<canvas id="myCanvas" width="578" height="200">
</canvas>
<div id="buttonWrapper">
<input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
</div>
</div>
<h2 id="status">
0, 0
</h2>
</body>
</html>
这对我来说非常适合缩放和鼠标移动。您可以对其进行自定义以上下使用鼠标滚轮。
【讨论】:
translatePos 的偏移量,以便视图保持居中。现在,如果您更改偏移和缩放,它将缩放图像的中心,而不是当前画布中心的位置。在重新缩放以保持缩放正确居中后,我找不到更新translatePos 的方法。有什么建议吗?
如果您有源图像或画布元素,并且您想在 400x400 画布上进行绘制,则可以使用 drawImage 方法来实现缩放。
例如,完整的视图可能是这样的
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
放大后的视图可能是这样的
ctx.drawImage(img, img.width / 4, img.height / 4, img.width / 2, img.height / 2, 0, 0, canvas.width, canvas.height);
drawImage的第一个参数是要绘制的图像元素或canvas元素,接下来的4个是要从源中采样的x、y、width和height,最后4个参数是x、y、width和height要在画布中绘制的区域。然后它将为您处理缩放。
您只需要根据缩放级别选择源样本的宽度和高度,并根据鼠标点击的位置减去计算的宽度和高度的一半来选择 x 和 y(但您需要确保矩形没有超出范围)。
【讨论】:
画布缩放和平移
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="" height=""
style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
console.log("canvas")
var ox=0,oy=0,px=0,py=0,scx=1,scy=1;
var canvas = document.getElementById("myCanvas");
canvas.onmousedown=(e)=>{px=e.x;py=e.y;canvas.onmousemove=(e)=>{ox-=(e.x-px);oy-=(e.y-py);px=e.x;py=e.y;} }
canvas.onmouseup=()=>{canvas.onmousemove=null;}
canvas.onwheel =(e)=>{let bfzx,bfzy,afzx,afzy;[bfzx,bfzy]=StoW(e.x,e.y);scx-=10*scx/e.deltaY;scy-=10*scy/e.deltaY;
[afzx,afzy]=StoW(e.x,e.y);
ox+=(bfzx-afzx);
oy+=(bfzy-afzy);
}
var ctx = canvas.getContext("2d");
function draw(){
window.requestAnimationFrame(draw);
ctx.clearRect(0,0,canvas.width,canvas.height);
for(let i=0;i<=100;i+=10){
let sx=0,sy=i;
let ex=100,ey=i;
[sx,sy]=WtoS(sx,sy);
[ex,ey]=WtoS(ex,ey);
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(ex, ey);
ctx.stroke();
}
for(let i=0;i<=100;i+=10){
let sx=i,sy=0;
let ex=i,ey=100;
[sx,sy]=WtoS(sx,sy);
[ex,ey]=WtoS(ex,ey);
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(ex, ey);
ctx.stroke();
}
}
draw()
function WtoS(wx,wy){
let sx=(wx-ox)*scx;
let sy=(wy-oy)*scy;
return[sx,sy];
}
function StoW(sx,sy){
let wx=sx/scx+ox;
let wy=sy/scy+oy;
return[wx,wy];
}
</script>
</body>
</html>
【讨论】:
IIRC Canvas 是一种光栅样式的位图。它不能缩放,因为没有可缩放的存储信息。
您最好的选择是在内存中保留两个副本(放大的和非放大的)并在单击鼠标时交换它们。
【讨论】:
一种选择是使用 css 缩放功能:
$("#canvas_id").css("zoom","x%");
【讨论】: