簡體   English   中英

如何從響應式畫布獲取圖像?

[英]How to get image from responsive canvas?

我需要從2個畫布生成1200x630的最終圖像,不一定要具有該尺寸,例如從移動設備查看應用程序。

這是畫布的一部分,我根據用戶動作繪制圖片和項目,它的工作原理。

<div>
    <canvas width="1200" height="630" id="canvas-foto">Tu navegador no soporta esta aplicaci&oacute;n</canvas>
    <canvas width="1200" height="630" id="canvas-marco">Tu navegador no soporta esta aplicaci&oacute;n</canvas>
    <canvas width="1200" height="630" id="canvas-wrapper">Tu navegador no soporta esta aplicaci&oacute;n</canvas>
</div>
<button id="btn_guardar">Guardar</button>

這將是負責生成圖像的JS的一部分,例如,只是松散在屏幕上,盡管我將它保存在服務器上。

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;
});

現在我必須實現這個響應,但重新調整畫布大小,最終圖像也將改變。 如何從較小的畫布獲得1200x630的圖像?

澄清用戶可以通過拖放操作重定位畫布內的元素。

問候!

您可以使用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&oacute;n</canvas> <canvas width="1200" height="630" id="canvas-marco">Tu navegador no soporta esta aplicaci&oacute;n</canvas> <canvas width="1200" height="630" id="canvas-wrapper">Tu navegador no soporta esta aplicaci&oacute;n</canvas> </div> <div id="controls"> <button id="btn_guardar">Guardar</button> <button id="btn_foto">foto <span>&#10003;</span> </button> <button id="btn_marco">marco <span>&#10003;</span> </button> <button id="btn_wrapper">wrapper <span>&#10003;</span> </button> </div> 

如果您需要在服務器上存儲的是用戶在畫布上移動不同對象后的最終圖像,則最佳解決方案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(); })(); 
 canvas { border: 1px solid } 
 <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> 

這是一個小提琴 ,其中保存到localStorage也有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM