Javascript 在边界内平滑地在画布周围平移
我发现的大多数其他解决方案都是以图像为边界,通过css工作,我无法让它们与画布一起工作 我想通过定义画布的任意百分比大小(例如2x-大小的两倍)来创建边界,该大小从画布中心展开,然后让画布视图(红色)在边界(绿色)内移动/平移,鼠标悬停在画布内-它从画布中心移动到边界的所有角落 就像平移方向上的这种行为一样 另外,我想Javascript 在边界内平滑地在画布周围平移,javascript,canvas,html5-canvas,pan,Javascript,Canvas,Html5 Canvas,Pan,我发现的大多数其他解决方案都是以图像为边界,通过css工作,我无法让它们与画布一起工作 我想通过定义画布的任意百分比大小(例如2x-大小的两倍)来创建边界,该大小从画布中心展开,然后让画布视图(红色)在边界(绿色)内移动/平移,鼠标悬停在画布内-它从画布中心移动到边界的所有角落 就像平移方向上的这种行为一样 另外,我想 使用响应画布大小而不是固定画布大小的解决方案 使用诸如CubicInOut放松等放松方式使平移平滑 要检测鼠标悬停在绘制的圆内。可能必须将坐标从屏幕更改为世界坐标才能使其正
- 使用响应画布大小而不是固定画布大小的解决方案
- 使用诸如CubicInOut放松等放松方式使平移平滑
- 要检测鼠标悬停在绘制的圆内。可能必须将坐标从屏幕更改为世界坐标才能使其正常工作。但也许他们的方法更简单
<html>
<head>
<meta charset="UTF-8">
<title>Panning</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
background: #eee;
padding: 20px 0;
}
.canvas-container {
height: 400px;
width: 100%;
margin-bottom: 40px;
border-radius: 10px;
background: #fff;
overflow: hidden;
}
canvas {
width: 100%;
height: inherit;
}
.container {
width: 60%;
margin: 0 auto;
}
</style>
</head>
<body>
<!-- CANVAS -->
<div class="container">
<div class="canvas-container">
<canvas id="canvas"></canvas>
</div>
</div>
<!-- SCRIPT -->
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width = canvas.clientWidth;
var height = canvas.height = canvas.clientHeight;
var panX = 0, panY = 0;
var scaleBorderFactor = 2; /* scale factor for the bounds */
var mouse = {
x: 0,
y: 0
}
function Circle(x, y, radius, color){
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function(ctx){
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,Math.PI*2,false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
/* Rect Stroke Borders for visual reference */
function RectBorder(x, y, w, h, c){
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.color = c;
this.draw = function(ctx){
ctx.strokeStyle = this.color;
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.width, this.height);
};
/* Draw rect from a center point */
this.drawAtCenter = function(ctx){
ctx.strokeStyle = this.color;
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.width, this.height);
};
this.toString = function(){
console.log("x: "+this.x+", y: "+this.y+", w: "+this.width+", h: "+this.height+", color = "+this.color);
}
}
function getMousePos(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: (event.clientX - rect.left),
y: (event.clientY - rect.top)
};
}
function insideCircle(circle, mouse){
var dist = Math.sqrt(Math.pow(circle.x - mouse.x,2) + Math.pow(circle.y - mouse.y,2));
console.log(circle.radius+", d = "+dist)
return dist <= circle.radius;
}
function lerp(start, end, percent){
return start*(1 - percent) + percent*end;
}
/* t: current time, b: beginning value, c: change in value, d: duration */
function easeInOutCubic(t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
}
var canvasBorder = new RectBorder(0,0,canvas.width,canvas.height,'red');
var boundsBorder = new RectBorder(-(canvas.width*scaleBorderFactor - canvas.width)/2,-(canvas.height*scaleBorderFactor - canvas.height)/2,canvas.width*scaleBorderFactor,canvas.height*scaleBorderFactor,'green');
var circle = new Circle(200,200,40,'blue');
/* Draw Update */
update();
function update(){
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
width = canvas.width = canvas.clientWidth;
height = canvas.height = canvas.clientHeight;
ctx.clearRect(0,0,width,height);
ctx.save();
/* MOUSE */
percentX = (mouse.x / width);
percentY = (mouse.y / height);
/* the 2 sides of boundsBorder */
var leftSide = (width*scaleBorderFactor - width)/2 - width;
var rightSide = (width*scaleBorderFactor - width)/2 + width;
var topSide = (height*scaleBorderFactor - height)/2 - width;
var bottomSide = (height*scaleBorderFactor - height)/2 + height;
newX = rightSide * percentX + leftSide * (1 - percentX);
newY = bottomSide * percentY + topSide * (1 - percentY);
/* maybe use easeInOutCubic for better smoothness */
panX = lerp(-newX, mouse.x, 0.1);
panY = lerp(-newY, mouse.y, 0.1);
if (insideCircle(circle, mouse)){
circle.color = "pink";
} else {
circle.color = "blue";
}
ctx.translate(panX,panY);
/* Draw both borders only for reference */
canvasBorder.draw(ctx);
boundsBorder.drawAtCenter(ctx);
/* Draw Circle */
circle.draw(ctx);
ctx.restore();
requestAnimationFrame(update);
}
/* Events */
function mousemove(e) {
mouse = getMousePos(canvas, e);
}
/* Event Listeners */
canvas.addEventListener('mousemove', mousemove);
</script>
</body>
</html>
var canvasBorder = new RectBorder(0,0,canvas.width,canvas.height,'red');
/* widthGap is the new leftSide formula.
* it is the gap differance between border and canvas
*/
var widthGap = (canvas.width*scaleBorderFactor - canvas.width)/2;
var heightGap = (canvas.height*scaleBorderFactor - canvas.height)/2;
var boundsBorder = new RectBorder(-widthGap,-heightGap,canvas.width+widthGap*2,canvas.height+heightGap*2,'green');
var circle = new Circle(200,200,40,'blue');
/* Draw Update */
update();
var newPercentX = 0, newPercentY = 0;
var percentX = 0, percentY = 0;
function update(){
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
width = canvas.width = canvas.clientWidth;
height = canvas.height = canvas.clientHeight;
ctx.clearRect(0,0,width,height);
ctx.save();
newPercentX = (mouse.x / width);
newPercentY = (mouse.y / height);
/* MOUSE */
percentX = lerp(percentX,newPercentX,0.05);
percentY = lerp(percentY,newPercentY,0.05);
panX = (widthGap) * percentX + (-widthGap) * (1 - percentX);
panY = (heightGap) * percentY + (-heightGap) * (1 - percentY);
ctx.translate(-panX,-panY);
if (insideCircle(circle, mouse)){
circle.color = "pink";
} else {
circle.color = "blue";
}
/* Draw both borders only for reference */
canvasBorder.draw(ctx);
boundsBorder.drawAtCenter(ctx);
/* Draw Circle */
circle.draw(ctx);
ctx.restore();
requestAnimationFrame(update);
}