canvas变形方法transform的可视化演示

canvas 的变形方法transform是三个基本变形方法的结合,他们是
translate——移动;scale——缩放 ;rotate ——旋转,在transform方法中分解为x,y两个方向的斜切。
他的参数是变形矩阵的六个数值:m11, m12, m21, m22, dx, dy
变形矩阵:
m11 m21  dx  
m12 m22 dy  
0  0  1  

对于transform方法的使用,其实很难把握,所以写了下面这个演示

<!doctype html>
<html>
<head>
<meta charset='UTF-8' />
<title>cssass.com</title>
<style>
#rule,#pad{float:left;margin:10px;}
#rule p{padding;0;margin:0;line-height:25px;}
#rule label{display:inline-block;width:80px;text-align:right;font-size:12px;}
#rule input{border:0;width:40px;}
#rule b{position:relative;display:inline-block;width:150px;height:10px;font-size:0;line-height:0;background:#fff;border:1px solid #aaa;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;}
#rule p a{position:absolute;top:-4px;left:50%;width:15px;height:15px;margin-left:-8px;border:1px solid #d3d3d3;background:#ececec;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;}
#rule p a:hover{border:1px solid #999;background:#dcdcdc;}
.footer{font-size:12px;padding:10px 0;}
</style>
</head>
<body>
<div id='rule'>
<h3>Transform方法可视化操作演示</h3>
<p onmousedown='G.change(this,event,4);'><label>水平缩放 m11: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='m11' type='text' /></p>
<p onmousedown='G.change(this,event,4);'><label>y轴斜切 m12: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='m12' type='text' /></p>
<p onmousedown='G.change(this,event,4);'><label>x轴斜切 m21: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='m21' type='text' /></p>
<p onmousedown='G.change(this,event,4);'><label>垂直缩放 m22: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='m22' type='text' /></p>
<p onmousedown='G.change(this,event,1000);'><label>平移 dx: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='dx' type='text' /></p>
<p onmousedown='G.change(this,event,1000);'><label>纵移 dy: </label> <b class='range'><a onfocus="blur();"  href='javascript:;'>&nbsp;</a></b> <input id='dy' type='text' /></p>
<div class='footer'>首先在右侧用鼠标画一矩形。<br />Javascript by <a href='http://ww.cssass.com'>cssass.com</a></div>
</div>
<canvas id="pad" width='800' height="600" style="position:relative;border:1px solid #c3c3c3;cursor:crosshair;">注意:ie9以下用户请绕行</canvas>
<script>
var $id=function(o){return document.getElementById(o);}
var con=$id("pad").getContext('2d');
var G={};
G.x1=G.y1=G.x2=G.y2=0;
G.val=[[4,1],[4,0],[4,0],[4,1],[1000,0],[1000,0]];
G.init=function(){
var list=$id('rule').getElementsByTagName('p');
var left, value;
for(var i=0; i<list.length; i++){
value = G.val[i][1];
left =(0.5 + G.val[i][1] / G.val[i][0] ) * 100;
list[i].getElementsByTagName('a')[0].style.left= left + '%';
list[i].getElementsByTagName('input')[0].value= value;
}
}
G.draw=function(){
G.init();
var e = arguments[0];
G.x1 = (e.layerX) ? e.layerX : e.offsetX,
G.y1 = (e.layerY) ? e.layerY : e.offsetY,
$id("pad").onmousemove=function(e){
con.clearRect(0,0,800,600);
G.x2= (e.layerX) ? e.layerX : e.offsetX;
G.y2= (e.layerY) ? e.layerY : e.offsetY;
con.save();
con.translate(G.x1,G.y1)
G.rect(G.x1,G.y1,G.x2,G.y2);
con.restore();
}
$id("pad").onmouseup=function(){
$id("pad").onmousedown=null;
$id("pad").onmousemove=null;
}
}
G.change=function(obj,e,l,v){
var o=obj.getElementsByTagName('a')[0];
var e = e ? e : window.event;
if(!window.event) {e.preventDefault();}
var tX=o.offsetLeft,
dx=e.clientX;
document.onmousemove=function(e){
var e = e ? e : window.event;
var len=tX+e.clientX-dx+8;
if(len>=0 && len<=150){
var rat=(len / 150) * 100;
o.style.left=rat+ "%";
obj.getElementsByTagName('input')[0].value =l * Math.round((rat - 50)*10)/1000;
G.transform();
}
if(window.event) e.returnValue=false;
}
document.onmouseup=function(){
document.onmousemove=null;
document.onmouseup=null;
}
}
G.transform=function(){
var m11=($id('m11').value == 0)? 0.001 : $id('m11').value,  //firefox下m11,m12值不能为0
m12=$id('m12').value,
m21=$id('m21').value,
m22=($id('m22').value == 0)? 0.001 : $id('m22').value,
dx=$id('dx').value,
dy=$id('dy').value;
con.clearRect(0,0,800,600);
con.save();
con.translate(G.x1,G.y1);  //变形的参考点设为图形的左上角
con.transform(m11, m12, m21, m22, dx, dy);
G.rect(G.x1,G.y1,G.x2,G.y2);
con.restore();
}
G.rect=function(x1,y1,x2,y2){
var grd=con.createLinearGradient(0, 0, x2 - x1, y2 - y1); //弄一个渐变效果
grd.addColorStop(0,"#3F5816");
grd.addColorStop(1,"#B40000");
con.fillStyle=grd;
con.fillRect(0, 0, x2 - x1, y2 - y1);
}
window.addEventListener("load", G.init, false);
$id("pad").addEventListener("mousedown", G.draw, false);
</script>
</body>
</html>


相关文章 bezierCurveTo方法的可视化演示:http://bbs.blueidea.com/thread-2999324-1-1.html

好消息! 
目前已经有一款Illustrator的插件支持导出canvas code:http://visitmix.com/labs/ai2canvas/

<think>好的,我现在需要处理用户关于HTML5 canvas属性及其应用场景的问题。首先,回顾用户之前的对话历史,用户之前询问了如何设置cursor支持中文,现在转向了canvas的相关问题。用户明确提到想了解canvas的属性及应用实例,并参考了之前的引用内容。 首先,我需要确认用户的需求。用户可能正在学习HTML5,特别是canvas元素,想要了解其基本属性和实际应用。用户提供的引用中提到了canvas的默认大小、如何设置大小、使用JavaScript操作canvas以及绘制线条的例子。这些都是基础内容,需要详细展开。 接下来,我需要整理canvas的主要属性。根据已有的知识,canvas的常见属性包括width、height,以及通过JavaScript获取的上下文(context)。这些属性控制画布的大小和绘图能力。同时,需要注意canvas的默认大小是300*150,用户可能需要知道如何正确设置尺寸,避免拉伸变形。 然后,应用场景方面,用户提到的引用中提到了HTML5游戏和数据可视化。这些都是canvas的典型应用,此外还有图像处理、动画效果、交互式图表等。需要举出具体的例子,比如小球运动的实例,来说明如何利用canvas实现这些效果。 用户可能对如何开始使用canvas感兴趣,所以需要提供基础的代码示例,比如如何获取canvas元素、获取上下文,以及绘制简单图形如线条、矩形、圆形等。此外,用户可能希望看到动态应用的例子,比如动画或游戏中的小球运动,这需要涉及定时器和对象封装的技巧。 另外,用户之前的对话中提到了面向对象编程,所以在应用实例部分,可以结合面向对象的方法,展示如何封装小球对象,实现多个小球的运动。这不仅能演示canvas的动态绘图能力,还能展示代码的组织结构,符合用户之前提到的引用内容。 需要注意用户可能存在的误区,比如直接通过CSS调整canvas的大小会导致画布内容拉伸,应该使用HTML属性或JavaScript来设置width和height。这一点需要特别强调,避免用户在使用时出现问题。 最后,生成的相关问题需要围绕用户可能进一步探索的方向,比如性能优化、高级绘图技巧、与其他技术的结合等,帮助用户深化理解。 总结下来,回答的结构应该是先介绍canvas的基础属性,再详细说明应用场景,辅以代码示例,最后提供相关问题引导用户深入学习。需要确保内容清晰,步骤明确,示例实用,并且语言符合中文习惯,避免技术术语的过度堆砌,保持易懂。</think>### HTML5 Canvas 属性及核心应用场景详解 #### 一、Canvas 核心属性 1. **`width` 与 `height`** - **功能**:定义画布的像素尺寸,默认值为 `300×150`。 - **正确设置方式**(避免拉伸): ```html <!-- 通过 HTML 属性直接设置 --> <canvas id="myCanvas" width="800" height="600"></canvas> ``` ```javascript // 通过 JavaScript 动态设置 const canvas = document.getElementById('myCanvas'); canvas.width = 800; // 直接赋值,非 CSS 样式 canvas.height = 600; ``` - **注意**:通过 CSS 设置 `width/height` 会拉伸画布内容,导致图像模糊,需优先使用属性设置[^1]。 2. **绘图上下文(`getContext`)** - **作用**:获取 2D 或 WebGL 绘图接口,所有绘图操作依赖此对象。 ```javascript const ctx = canvas.getContext('2d'); // 获取 2D 上下文 ``` 3. **图像数据操作** - **`ImageData` 对象**:通过 `ctx.getImageData()` 获取像素数据,用于图像处理。 ```javascript const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); ``` --- #### 二、Canvas 基础绘图操作 1. **路径绘制** - **线条绘制流程**(示例代码): ```javascript ctx.beginPath(); // 开始路径 ctx.moveTo(50, 50); // 起点 ctx.lineTo(200, 100); // 终点 ctx.strokeStyle = 'blue'; // 线条颜色 ctx.lineWidth = 3; // 线条宽度 ctx.stroke(); // 绘制线条 ``` 2. **形状填充** - **矩形与圆形**: ```javascript // 矩形(填充) ctx.fillStyle = '#FFA500'; // 填充颜色 ctx.fillRect(30, 30, 100, 80); // x, y, width, height // 圆形(描边) ctx.beginPath(); ctx.arc(150, 150, 40, 0, Math.PI * 2); // 圆心(x,y), 半径, 起始角, 结束角 ctx.stroke(); ``` --- #### 三、Canvas 典型应用场景 1. **动态图形与游戏开发** - **实例:多小球碰撞动画**(面向对象封装): ```javascript class Ball { constructor(x, y, radius, color) { this.x = x; this.y = y; this.radius = radius; this.color = color; this.dx = Math.random() * 4 - 2; // 随机水平速度 this.dy = Math.random() * 4 - 2; // 随机垂直速度 } draw(ctx) { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = this.color; ctx.fill(); } update(canvas) { // 边界碰撞检测 if (this.x + this.radius > canvas.width || this.x - this.radius < 0) { this.dx = -this.dx; } if (this.y + this.radius > canvas.height || this.y - this.radius < 0) { this.dy = -this.dy; } this.x += this.dx; this.y += this.dy; } } // 创建10个小球 const balls = Array.from({ length: 10 }, () => new Ball(Math.random() * 300, Math.random() * 150, 10, '#FF6B6B') ); // 动画循环 function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); balls.forEach(ball => { ball.update(canvas); ball.draw(ctx); }); requestAnimationFrame(animate); } animate(); ``` **效果**:多个彩色小球在画布内随机运动并反弹边界[^1]。 2. **数据可视化** - **动态折线图示例**: ```javascript // 模拟数据 const data = [65, 59, 80, 81, 56, 55, 40]; // 绘制折线 ctx.beginPath(); ctx.moveTo(50, canvas.height - 50); data.forEach((value, index) => { const x = 50 + index * 50; const y = canvas.height - 50 - value; ctx.lineTo(x, y); }); ctx.strokeStyle = 'green'; ctx.stroke(); ``` 3. **图像处理与滤镜** - **灰度滤镜实现**: ```javascript const image = new Image(); image.src = 'photo.jpg'; image.onload = () => { ctx.drawImage(image, 0, 0); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { const avg = (data[i] + data[i+1] + data[i+2]) / 3; data[i] = avg; // Red data[i+1] = avg; // Green data[i+2] = avg; // Blue } ctx.putImageData(imageData, 0, 0); }; ``` --- ### 四、高级技巧与优化建议 - **双缓冲技术**:通过离屏 Canvas 预渲染复杂图形,避免闪烁。 - **性能优化**:减少频繁的 `getImageData/putImageData` 操作,使用 `transform` 替代重复绘制。 - **响应式适配**:监听窗口大小变化,动态调整 Canvas 尺寸: ```javascript window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); ``` --- ### 相关问题 1. 如何通过 Canvas 实现用户交互(如拖拽图形)? 2. Canvas 与 SVG 在图形渲染上有何本质区别? 3. 在复杂动画中如何避免 Canvas 渲染卡顿? 4. WebGL 与 2D Canvas 的核心差异是什么?各适合哪些场景? [^1]: 参考《HTML5 Canvas核心技术》及MDN文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值