HTML5 холст перерисовать при изменении размера
У меня есть два элемента холста, и мне нужно изменить их размер при нажатии кнопки.
<div class="sDetails"><div>
<div id="canvasDiv" style="width: 310px;"><canvas id="canvasGraph"></canvas></div></div>
<div class="kDetails"><div><div>
<div id="canvasDiv" style="width: 310px; height: 240px;"><canvas id="canvasGraph"></canvas></div></div>
и сценарий:
var sketch;var sketch_sl;var onPaint;var canvas=null;var ctx=null;var tmp_ctx=null;
function drawCanvas(div) {
canvas = document.querySelector(div + " #canvasGraph");
ctx = canvas.getContext('2d');
sketch = document.querySelector(div + " #canvasDiv");
sketch_sl = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
tmp_canvas = document.createElement('canvas');
tmp_ctx = tmp_canvas.getContext('2d');
tmp_canvas.id = 'tmp_canvas';
tmp_canvas.width = canvas.width;
tmp_canvas.height = canvas.height;
sketch.appendChild(tmp_canvas);
функция перерисовки:
// here I must redraw my lines resized 2 times ( *cScale ) where cScale=2 or =1
function drawScales(ctx, canvas)
ctx.strokeStyle = 'green';
ctx.fillStyle = 'green';
ctx.beginPath();
ctx.moveTo(5, 0);
ctx.lineTo(0, canvas.height);
scaleStep = 24*cScale;
по какой-то причине это работает очень плохо, старые позиции остаются. Есть ли способ полностью удалить весь холст и добавить его или полностью перерисовать?
Я старался canvas.width=canvas.width
, пытался ctx.clearRect(0, 0, canvas.width, canvas.height);tmp_ctx.clearRect(0, 0, canvas.width, canvas.height);
, пытался $(".sDetails #canvasGraph")[0].reset();
логически, drawCanvas(".sDetails");drawLines(ctx, canvas);
следует перерисовать его с нуля, но это не так.
3 ответа
Я решил использовать переменную масштаба, чтобы изменить размеры своих весов. Я изменяю размер холста canvas.width *= 2;
и затем я перерисовываю свои весы.
var scaleStep;
и используйте добавить его в код: ctx.lineTo(12*24*cScale+12, canvas.height-24);
где масштабирование должно быть сделано. Параметр scaleStep равен 2 при максимизации холста и 1 при возврате к исходному размеру.
Изменить размер элемента canvas width
& height
и использовать context.scale
перерисовать оригинальные рисунки в их новом масштабе.
Изменение размера элемента canvas автоматически удалит все рисунки с холста.
Изменение размера также автоматически сбрасывает все свойства контекста до значений по умолчанию.
С помощью
context.scale
Это полезно, потому что тогда холст автоматически масштабирует исходные рисунки, чтобы уместить их на новом размере холста.Важное замечание: Canvas не будет автоматически перерисовывать исходные чертежи... необходимо заново выполнить исходные команды рисования.
Иллюстрация с двумя полотнами одинакового размера (их размеры контролируются регулятором диапазона)
Иллюстрация с измененным размером левого холста
Иллюстрация с правым холстом увеличена
Вот пример кода и демо. Эта демонстрация использует элементы range для управления изменением размера, но вы также можете выполнить изменение размера + перерисовку внутри window.onresize
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
var canvas2=document.getElementById("canvas2");
var ctx2=canvas2.getContext("2d");
var originalWidth=canvas1.width;
var originalHeight=canvas1.height;
var scale1=1;
var scale2=1;
$myslider1=$('#myslider1');
$myslider1.attr({min:50,max:200}).val(100);
$myslider1.on('input change',function(){
var scale=parseInt($(this).val())/100;
scale1=scale;
redraw(ctx1,scale);
});
$myslider2=$('#myslider2');
$myslider2.attr({min:50,max:200}).val(100);
$myslider2.on('input change',function(){
var scale=parseInt($(this).val())/100;
scale2=scale;
redraw(ctx2,scale);
});
draw(ctx1);
draw(ctx2);
function redraw(ctx,scale){
// Resizing the canvas will clear all drawings off the canvas
// Resizing will also automatically clear the context
// of all its current values and set default context values
ctx.canvas.width=originalWidth*scale;
ctx.canvas.height=originalHeight*scale;
// context.scale will scale the original drawings to fit on
// the newly resized canvas
ctx.scale(scale,scale);
draw(ctx);
// always clean up! Reverse the scale
ctx.scale(-scale,-scale);
}
function draw(ctx){
// note: context.scale causes canvas to do all the rescaling
// math for us, so we can always just draw using the
// original sizes and x,y coordinates
ctx.beginPath();
ctx.moveTo(150,50);
ctx.lineTo(250,150);
ctx.lineTo(50,150);
ctx.closePath();
ctx.stroke();
ctx.fillStyle='skyblue';
ctx.beginPath();
ctx.arc(150,50,20,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(250,150,20,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.beginPath();;
ctx.arc(50,150,20,0,Math.PI*2);
ctx.fill();
ctx.stroke();
}
$("#canvas1, #canvas2").mousemove(function(e){handleMouseMove(e);});
var $mouse=$('#mouse');
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
var bb=e.target.getBoundingClientRect();
mouseX=parseInt(e.clientX-bb.left);
mouseY=parseInt(e.clientY-bb.top);
if(e.target.id=='canvas1'){
$mouse.text('Mouse1: '+mouseX/scale1+' / '+mouseY/scale1+' (scale:'+scale1+')');
}else{
$mouse.text('Mouse2: '+mouseX/scale2+' / '+mouseY/scale2+' (scale:'+scale2+')');
}
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div>Resize left canvas</div>
<input id=myslider1 type=range><br>
<div>Resize right canvas</div>
<input id=myslider2 type=range><br>
<h4 id=mouse>Mouse coordinates:</h4>
<canvas id="canvas1" width=300 height=300></canvas>
<canvas id="canvas2" width=300 height=300></canvas>
Если вам нужны независимые от масштаба позиции, вы можете вместо этого использовать нормализованные значения ([0, 1]) и использовать размер холста в качестве масштабного коэффициента. Таким образом, вы можете масштабировать и хранить значения без особой заботы о реальном размере цели.
Вы также сможете использовать положения мыши почти как есть и нормализовать, просто разделив их по размеру холста.
Например:
При рендеринге точка (1,1) всегда будет рисоваться в правом нижнем углу, как вы это делаете (1 * canvas.width, 1 * canvas.height)
,
Когда вы сохраняете точку, вы используете положение мыши и делите ее на размер холста, например, если я щелкну в правом нижнем углу холста размером 400x200, точки будут 400/400 = 1, 200/200 = 1
Обратите внимание, что ширина и высота будут исключительными (т.е. ширина-1 и т. Д.), Но ради простоты...
пример
В этом примере вы можете начать с любого размера холста, нарисовать нормализованные точки, изменить размер холста и перерисовать точки пропорционально относительно исходной позиции.
var rng = document.querySelector("input"),
c = document.querySelector("canvas"),
ctx = c.getContext("2d"),
points = [];
// change canvas size and redraw all points
rng.onchange = function() {
c.width = +this.value;
render();
};
// add a new normalized point to array
c.onclick = function(e) {
var r = this.getBoundingClientRect(), // to adjust mouse position
x = e.clientX - r.left,
y = e.clientY - r.top;
points.push({
x: x / c.width, // normalize value to range [0, 1]
y: y / c.height
}); // store point
render(); // redraw (for demo)
};
function render() {
ctx.clearRect(0, 0, c.width, c.height); // clear canvas
ctx.beginPath(); // clear path
for(var i = 0, p; p = points[i]; i++) { // draw points as fixed-size circles
var x = p.x * c.width, // normalized to absolute values
y = p.y * c.height;
ctx.moveTo(x + 5, y);
ctx.arc(x, y, 5, 0, 6.28);
ctx.closePath();
}
ctx.stroke();
}
canvas {background:#ddd}
<h3>Click on canvas to add points, then resize</h3>
<label>Width: <input type="range" min=50 max=600 value=300></label><br>
<canvas></canvas>