我想知道是否有办法使用CSS3 Matrix3D转换将图像绘制到画布中。使用的上下文是2D
一个用于渲染堆叠图层的图像图层和一个用matrix3D
转换的图像图层(因为我没有设法在画布上绘制它)。
基本上我想要实现的是将transform: matrix3d(0.87, 0, 0.5, -0.00025, 0, 1, 0, 0, -0.5, 0, 0.87, 0, 0, 550, 0, 1)
转换为2D上下文中的绘图画布方法。
有可能吗?现在,我对画布上方的CSS3层非常好,但我正在开发的应用程序必须将画布导出到实际的图像文件(意味着发送给用户)。
这是一个片段,说明了我目前显示转换图层的方式。所以这里的目标是实际将“占位符”转换后的图像渲染到画布中
#canvas {
background: tomato;
height: 100vh;
width: 100vw;
position: relative;
}
.viewport .transformed-layer {
height: 72%;
position: absolute;
left: 35%;
top: calc(21% - 550px);
-webkit-transform: rotate(-1.5deg) matrix3d(0.87, 0, 0.5, -0.00025, 0, 1, 0, 0, -0.5, 0, 0.87, 0, 0, 550, 0, 1);
transform: rotate(-1.5deg) matrix3d(0.87, 0, 0.5, -0.00025, 0, 1, 0, 0, -0.5, 0, 0.87, 0, 0, 550, 0, 1);
opacity: .9;
}
<div class='viewport'>
<div id='canvas'>This is a div simulating the canvas element with some drawed image</div>
<img class='transformed-layer' src='http://via.placeholder.com/300x300' />
</div>
答案 0 :(得分:2)
有一种黑客攻击可能不符合未来读者的要求,但可能适合你:
画布可以绘制SVG图像,SVG图像可以通过CSS转换。 因此,您可以将当前画布转换为dataURL,将此dataURL设置为SVGImage元素的href,然后将其应用于CSSTransform,然后将所有这些作为svg图像导出,并将其绘制到画布上。
以下是概念的粗略证明:
function getTransformedCanvas(canvas, CSSTransform){
return new Promise(function(res, rej){
var dim = getTransformedDimensions(canvas, CSSTransform);
var xlinkNS = "http://www.w3.org/1999/xlink",
svgNS = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(svgNS, 'svg'),
defs = document.createElementNS(svgNS, 'defs'),
style = document.createElementNS(svgNS, 'style'),
image = document.createElementNS(svgNS, 'image');
image.setAttributeNS(xlinkNS, 'href', canvas.toDataURL());
image.setAttribute('width', canvas.width);
image.setAttribute('height', canvas.height);
style.innerHTML = 'image{transform:'+CSSTransform+';}';
svg.appendChild(defs);
defs.appendChild(style);
var rect = document.createElement('rect');
svg.appendChild(image);
svg.setAttribute('width', dim.width);
svg.setAttribute('height', dim.height);
var svgStr = new XMLSerializer().serializeToString(svg);
var img = new Image();
img.onload = function(){res(img)};
img.onerror = rej;
img.src = URL.createObjectURL(new Blob([svgStr], {type:'image/svg+xml'}));
});
}
function getTransformedDimensions(canvas, CSSTransform){
var orphan = !canvas.parentNode;
if(orphan) document.body.appendChild(canvas);
var oldTrans = getComputedStyle(canvas).transform;
canvas.style.transform = CSSTransform;
var rect = canvas.getBoundingClientRect();
canvas.style.transform = oldTrans;
if(orphan) document.body.removeChild(canvas);
return rect;
}
// create a simple checkerboard
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 30;
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'orange';
ctx.fillRect(0,0,15, 15);
ctx.fillRect(15,15,15, 15);
var pattern = ctx.createPattern(canvas, 'repeat');
canvas.width = canvas.height = 300;
ctx.fillStyle = pattern;
ctx.fillRect(0,0,300,300);
getTransformedCanvas(canvas,
'translateY(-540px) rotate(-1.5deg) matrix3d(0.87, 0, 0.5, -0.00025, 0, 1, 0, 0, -0.5, 0, 0.87, 0, 0, 550, 0, 1)'
)
.then(function(img){
inScreen.width = img.width;
inScreen.height = img.height;
inScreen.getContext('2d').drawImage(img, 0,0);
})
.catch(console.error);
&#13;
canvas {
border:1px solid;
}
&#13;
<canvas id="inScreen"></canvas>
&#13;
但是请注意,只要在它上面绘制svg iamge,旧版本的IE确实会污染画布......