我需要从2个画布生成1200x630的最终图像,不一定要具有该尺寸,例如从移动设备查看应用程序。
这是画布的一部分,我根据用户操作绘制图片和项目,它有效。
var canvas_marcos = document.getElementById("canvas-marco");
var ctx_marcos = canvas_marcos.getContext("2d");
var canvas_foto = document.getElementById("canvas-foto");
var ctx_foto = canvas_foto.getContext("2d");
var canvas_wrapper = document.getElementById("canvas-wrapper");
var ctx_wrapper = canvas_wrapper.getContext("2d");
$('#btn_guardar').click(function(){
ctx_wrapper.drawImage(canvas_foto, 0, 0);
ctx_wrapper.drawImage(canvas_marcos, 0, 0);
var dataURL = canvas_wrapper.toDataURL();
var img = new Image();
img.onload = function(){
document.body.appendChild(img);
}
img.src = dataURL;
});
这将是负责生成图像的JS的一部分,例如,只是在屏幕上松动,尽管我将其保留在服务器上。
{{1}}
现在我必须实现这种响应,但重新调整画布大小,最终图像也会改变。如何从较小的画布获得1200x630的图像?
说明用户可以通过拖放操作重新定位画布内的元素。下降。
问候!
答案 0 :(得分:0)
您可以使用CSS更改画布显示大小。此示例将宽度设置为100%缩小或增大图像而不更改画布。
var canvas_marcos = document.getElementById("canvas-marco");
var ctx_marcos = canvas_marcos.getContext("2d");
var canvas_foto = document.getElementById("canvas-foto");
var ctx_foto = canvas_foto.getContext("2d");
var canvas_wrapper = document.getElementById("canvas-wrapper");
var ctx_wrapper = canvas_wrapper.getContext("2d");
$('#btn_guardar').click(function() {
ctx_wrapper.drawImage(canvas_foto, 0, 0);
ctx_wrapper.drawImage(canvas_marcos, 0, 0);
var dataURL = canvas_wrapper.toDataURL();
var img = new Image();
img.style.position = "absolute";
img.style.left = "0";
img.style.top = "0";
img.style.width = "100%";
img.onload = function() {
document.body.appendChild(img);
this.addEventListener("click", function() {
this.parentElement.removeChild(this);
reset();
});
}
img.src = dataURL;
});
// added by me
function toggleCanvas() {
$(this).toggleClass('off');
var can_id = "canvas-" + this.id.replace("btn_", "");
$('#' + can_id).toggleClass('hide');
}
$('#btn_foto').click(toggleCanvas);
$('#btn_marco').click(toggleCanvas);
$('#btn_wrapper').click(toggleCanvas);
function clear(ctx, color, text, y_offset) {
ctx.fillStyle = color;
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.clearRect(0,0,w,h);
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = "white";
ctx.font = "50px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, w / 2, h / 2 + y_offset);
}
function reset() {
clear(ctx_foto, "rgba(0,0,0,.7)", "canvas-foto", 0);
clear(ctx_marcos, "rgba(0,100,0,.7)", "canvas-marco", 50);
clear(ctx_wrapper, "rgba(10,30,130,.7)", "canvas-wrapper", 100);
}
reset();
body {
padding: 0;
margin: 0;
}
#canvas-foto,
#canvas-marco,
#canvas-wrapper {
width: 100%;
margin: 0;
position: absolute;
left: 0;
top: 0;
}
#controls {
position: absolute;
background-color: #00CC66;
padding: 10px;
}
.hide {
display: none;
}
button.off {
background-color: lightgray;
color: gray;
border-color: gray;
}
button.off span {
visibility: hidden;
}
button {
background-color: white;
color: black;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<canvas width="1200" height="630" id="canvas-foto">Tu navegador no soporta esta aplicación</canvas>
<canvas width="1200" height="630" id="canvas-marco">Tu navegador no soporta esta aplicación</canvas>
<canvas width="1200" height="630" id="canvas-wrapper">Tu navegador no soporta esta aplicación</canvas>
</div>
<div id="controls">
<button id="btn_guardar">Guardar</button>
<button id="btn_foto">foto <span>✓</span>
</button>
<button id="btn_marco">marco <span>✓</span>
</button>
<button id="btn_wrapper">wrapper <span>✓</span>
</button>
</div>
答案 1 :(得分:0)
如果您需要在服务器上存储的是用户在画布上移动不同对象后的最终图像,则最佳解决方案IMO将对象位置存储为JSON字符串并重绘它而不是保存渲染图像。
您的服务器上的数据会小得多,您的用户也可以再次修改显示。
这样,您就可以在每个屏幕尺寸上正确地重绘它,避免CSS抖动,甚至可以以任何你想要的尺寸导出。
通过使用ctx.scale()
,每个绘图操作甚至可以为任何比例保持相同的位置,您只需要为鼠标事件计算它。
(function() {
var ctx = canvas.getContext('2d');
////////////////////
// Object Storage //
////////////////////
// unfortunately, localStorage on stack-snippet will throw a security exception ...
/*
// get saved from localStorage, could be from server as well
var fromStorage = function(){
var str = localStorage.getItem('objects');
if(!str) return false;
return JSON.parse(str);
};
// save to localStorage or server
var toStorage = function(){
localStorage.setItem('objects', JSON.stringify(objects));
}
*/
// ... so just show the string that could be saved on server
var toStorage = function() {
log.innerHTML = JSON.stringify(objects);
};
save.onclick = toStorage;
// initiate the objects previously stored or default one
// var objects = fromStorage() || [{...}] Once again won't work in stack-snippets
var objects = [
{type:'rect', x:900, y:360, width:100, height:100, color:'blue'},
{type:'circle', x:150, y:60, width:72, height:72, color:'red'},
{type:'image', url:"http://lorempixel.com/500/500", x:500, y:250, width: 300, height:300}
];
// initialise our canvas
var init = function() {
// set the canvas' size and get the ratio
setSize(sizes[0]);
// check if there are image to load
for (var i = 0; i < objects.length; i++) {
if (objects[i].type === 'image') {
imagesToLoad++;
loadImage(objects[i]);
}
}
// if there's none, draw already
if (!imagesToLoad) draw();
};
// we only pass the desired width since we'll get the height from the ratio
var setSize = function(width) {
// set the canvas width
canvas.width = width;
// get the ratio of the current width divided by the desired one
// store it in the canvas element so we can use it after in mouse events
var ratio = canvas.ratio = canvas.width / 1200;
// set our canvas height
canvas.height = ratio * 630;
// set the context scale to the ratio so we don't care about it while drawing
ctx.scale(ratio, ratio);
}
// the drawing part
var draw = function() {
// clear the canvas at the default size since we changed the context's scale
ctx.clearRect(0, 0, 1200, 630);
// iterate through our objects array
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
// set the current color to the one of the object
ctx.fillStyle = obj.color;
// do different drawing operations based on object's type
switch (obj.type) {
case 'rect':
ctx.fillRect(obj.x, obj.y, obj.width, obj.height);
break;
case 'circle':
ctx.beginPath();
ctx.arc(obj.x + obj.width / 2, obj.y + obj.width / 2, obj.width / 2, Math.PI * 2, 0);
ctx.fill();
break;
case 'image':
ctx.drawImage(obj.img, obj.x, obj.y, obj.width, obj.height);
break;
}
}
};
var imagesToLoad = 0;
// a function to load all our image resources
var loadImage = function(obj) {
var img = new Image();
img.onload = function() {
obj.img = this;
if (!--imagesToLoad)
draw();
}
img.src = obj.url;
};
//////////////////
// mouse Events //
//////////////////
var activeObjects;
var mousedownHandler = function(e) {
var rect = canvas.getBoundingClientRect();
var x = (e.clientX - rect.left) / canvas.ratio;
var y = (e.clientY - rect.top) / canvas.ratio;
activeObjects = getActiveObjects(x, y);
};
var mouseupHandler = function(e) {
// we stopped dragging, reset the activeObjects array
activeObjects = null;
}
var mousemoveHandler = function(e) {
// if there is no object being dragged
if (!activeObjects) return;
// x and y coordinates have to be scaled by our actual ratio
var rect = canvas.getBoundingClientRect();
var x = (e.clientX - rect.left) / canvas.ratio;
var y = (e.clientY - rect.top) / canvas.ratio;
// iterate through all active objects
for (var i = 0; i < activeObjects.length; i++) {
// and update their position
update(activeObjects[i], x, y);
}
};
var getActiveObjects = function(x, y) {
var arr = [];
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
if (obj.x < x && obj.x + obj.width > x && obj.y < y && obj.y + obj.height > y)
arr.push(obj);
}
if (!arr.length) return null;
else return arr;
};
var update = function(obj, x, y) {
obj.x = x - (obj.width / 2);
obj.y = y - (obj.height / 2);
draw();
}
canvas.addEventListener('mousedown', mousedownHandler);
canvas.addEventListener('mouseup', mouseupHandler);
canvas.addEventListener('mousemove', mousemoveHandler);
/////////////////////////////
// Button events (for demo) //
/////////////////////////////
// store different sizes for our canvas
var sizes = [300, 200, 600, 3000];
var currentSize = 0;
resize.onclick = function() {
// iterate through the sizes array
setSize(sizes[++currentSize % sizes.length]);
draw();
};
// randomise our objects shapes and position
rand.onclick = function() {
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
obj.x = Math.random() * 1000;
obj.y = Math.random() * 500;
obj.width = Math.random() * 500;
obj.height = (obj.type === 'circle') ? obj.width : Math.random() * 500;
}
draw();
}
// Let's go !
init();
})();
&#13;
canvas {
border: 1px solid
}
&#13;
<button id="resize">resize canvas</button>
<button id="save">save</button>
<button id="rand">randomize</button><br>
<canvas id="canvas"></canvas>
<br><p id="log"></p>
&#13;
Here is a fiddle保存到localStorage也可以。