实现Canvas2D绘图 使元素绕中心居中旋转

  我之前用canvas写了个头像剪切的demo,但是关于让载入的图片旋转是个问题,虽然通过其它方法实现了,但是感觉并不太好,于是查了些资料,想试着重新做一下canvas的旋转。

在开始之前,先让我们来做一些准备工作:

 1 (function () {
 2     // 设置画布的宽高
 3     var width = 300,
 4         heigh = 100,
 5         cache = {}; // 存储canvas上下文
 6
 7     // 获取绘图上下文
 8     function getCtx(name, w, h) {
 9         var cv = document.getElementById(name),
10             ctx = cv.getContext(‘2d‘),
11             wh = getWH(w, h);
12
13         w = wh[0];
14         h = wh[1];
15
16         cv.width = w;
17         cv.height = h;
18
19         ctx && (cache[‘name‘] = ctx);
20         init(ctx);
21         return ctx;
22     }
23
24     // 设置角度
25     function (ctx, deg) {
26         ctx.rotate(deg / 180 * Math.PI); // 转成角度值
27     }
28
29     // 填充画布
30     function fill(ctx, color, arr) {
31         ctx.fillStyle = color;
32         ctx.fillRect(arr[0], arr[1], arr[2], arr[3]);
33     }
34
35     // 格式化画布
36     function init(ctx, w, h) {
37         var color = ‘#333‘, // 填充背景色
38             wh = getWH(w, h);
39
40         w = wh[0];
41         h = wh[1];
42
43         fill(ctx, color, [0, 0, w, h]);
44     }
45
46     // 进行位移
47     function translate(ctx, x, y) {
48         ctx.translate(x, y);
49     }
50
51     function getWH(w, h) {
52         w = w || width;
53         h = h || height;
54         return [w, h];
55     }
56
57 })();

准备完毕,先来绘制一个简单的矩形

  

 1 // d1 2  var cv1 = getCtx(‘cv1‘); 3 fill(cv1, ‘#fff‘, [125, 25, 50, 50]); 
					

  然后,我们试着让它旋转10deg

1 // d2
2     var cv2 = getCtx(‘cv2‘);
3     rotate(cv2, 10);
4     fill(cv2, ‘#fff‘, [125, 25, 50, 50]);

再看看旋转30deg会变成什么样

1 // d3
2     var cv3 = getCtx(‘cv3‘);
3     rotate(cv3, 30);
4     fill(cv3, ‘#fff‘, [125, 25, 50, 50]);

现在已经可以看出了,canvas旋转rotate是以画布左上角为中心点旋转的,由此我们可以想象得到90deg的样子

 1 .box2 {
 2         margin: 0 auto;
 3         width: 300px;
 4         line-height: 100px;
 5         background: #333;
 6         text-align: center;
 7         color: #fff;
 8     }
 9
10     .box3 {
11         margin: 0 auto;
12         width: 300px;
13         line-height: 100px;
14         background: #666;
15         text-align: center;
16         color: #fff;
17         transform: rotate(90deg) translate(0, 200px);
18     }

因此,就像css3通过transform-origin来修改旋转的中心一样的道理,我们使用translate为canvas修改旋转中心即可 ctx.translate(canvas.width / 2, canvas.height / 2);

使左上角偏移到宽高的一半的位置(中点)

1 //d4
2     var cv4 = getCtx(‘cv4‘);
3     translate(cv4, width / 2, height / 2);
4     fill(cv4, ‘#fff‘, [0, 0, width, height]);

那么现在再一次旋转90deg会得到我们想要的效果吗?

1 //d5
2     var cv5 = getCtx(‘cv5‘);
3     translate(cv5, width / 2, height / 2);
4     rotate(cv5, 90);
5     fill(cv5, ‘#fff‘, [0, 0, width, height]);

事实证明,还不行,但是已经靠近了,从现在看来只要再偏移一次回到原来的点就可以了就可以了

1 //d6
2     var cv6 = getCtx(‘cv6‘);
3     translate(cv6, width / 2, height / 2);
4     rotate(cv6, 90);
5     translate(cv6, -width / 2, -height / 2);
6     fill(cv6, ‘#fff‘, [0, 0, width, height]);

至于为什么会这样,请看下图:

或者猛戳这里看示例!!

所以现在实现了围绕中心旋转,而实现元素居中就简单了,正如以上的示例所展示的,正中的正方形已然居中,因为我在一开始就给它定好了刚好居中的开始坐标:

1 fill(cv3, ‘#fff‘, [125, 25, 50, 50]);

就好像position居中定位一样,这里的居中定位也一样计算:

1 (默认宽高为300 * 100) 2 (width / 2) - (50 / 2) = 125; 3 (height / 2) - (50 / 2) = 25;

我们把旋转和居中这些来封装一下,方便使用,代码如下:

 1 RotateCenter.prototype = {
 2         constructor: RotateCenter,
 3
 4         init: function (id, w, h) {
 5             this.width = w = w || this.width;
 6             this.height = h = h || this.height;
 7
 8             var canvas = this.getContext(id, ‘2d‘);
 9
10             // 设置宽高
11             this.setSize(canvas, w, h);
12         },
13
14         // 获取上下文
15         getContext: function (id, type) {
16             var canvas = document.getElementById(id),
17                 nowCtx = canvas.getContext(type);
18
19             this.cache[id] = nowCtx;
20             return canvas;
21         },
22
23         // 填充画布
24         fill: function (arr, color) {
25             this.nowCtx.fillStyle = color;
26             this.nowCtx.fillRect(arr[0], arr[1], arr[1] ? arr[1] : this.width, arr[2] ? arr[2] : this.height);
27         },
28
29         setSize: function (c, w, h) {
30             c.width = w;
31             c.height = h;
32         },
33
34         // 旋转
35         rotate: function (deg) {
36             this.nowCtx.rotate(deg / 180 * Math.PI);
37         },
38
39         // 位移
40         translate: function (x, y) {
41             this.nowCtx.translate(x, y);
42         },
43
44         // 切换上下文
45         checkout: function (id) {
46             this.nowCtx = this.cache[id];
47         },
48
49         // 绘制不居中绕中心旋转矩形
50         rotateRect: function (arr, color, deg) {
51             var w = this.width / 2,
52                 h = this.height / 2;
53
54             this.translate(w, h);
55             this.rotate(deg);
56             this.translate(-w, -h);
57             this.fill(arr, color);
58         },
59
60         // 绘制居中不绕中心旋转矩形
61         centerRect: function (width, height, color) {
62             var w = this.width / 2,
63                 h = this.height / 2,
64                 w1 = width / 2,
65                 h1 = height / 2;
66
67             this.fill([w - w1, h - h1, width, height], color);
68         },
69
70         // 绘制居中同时绕中心旋转矩形
71         centerRotateRect: function (width, height, deg, color) {
72             var w = this.width / 2,
73                 h = this.height / 2,
74                 w1 = width / 2,
75                 h1 = height / 2;
76
77             this.translate(w, h);
78             this.rotate(deg);
79             this.translate(-w, -h);
80             this.fill([w - w1, h - h1, width, height], color);
81         }
82     };

现在来测试一下:

绘制居中同时绕中心旋转矩形

45deg

1 // d7
2     var rc = new RotateCenter();
3     rc.init(‘cv7‘);
4     rc.centerRotateRect(50, 50, 45, ‘#fff‘);

163deg

	 1 // d8 2  rc.init(‘cv8‘); 3 rc.centerRotateRect(50, 50, 163, ‘#fff‘); 
				

绘制居中不绕中心旋转矩形

	 1 // d9 2  rc.init(‘cv9‘); 3 rc.centerRect(60, 60, ‘#fff‘); 
				

绘制不居中绕中心旋转矩形

30deg

278deg

1 // d10
2     rc.init(‘cv10‘);
3     rc.rotateRect([50, 50, 50, 50], ‘#fff‘, 30);
4
5     // d11
6     rc.init(‘cv11‘);
7     rc.rotateRect([50, 50, 50, 50], ‘#fff‘, 278);

从示例来看,rotateRect方法有点不太理想,而在这里想要的就是centerRotateRect方法的效果,所以到此OVER。

如有不正确的地方,欢迎指出!!!

原文地址:https://www.cnblogs.com/LiQingsong/p/8570804.html

时间: 2024-11-08 20:48:40

实现Canvas2D绘图 使元素绕中心居中旋转的相关文章

CSS3 : transform 与 transform-origin 属性可以使元素样式发生转变

CSS3 : transform 用于元素样式的转变,比如使元素发生位移.角度变化.拉伸缩小.按指定角度歪斜 transform结合transition可实现各类动画效果 transform : transform 兼容各浏览器写法如下: 1 transform: /* 转变样式 */; 2 -ms-transform: /* 转变样式 */; /* IE 9 */ 3 -webkit-transform: /* 转变样式 */; /* Safari and Chrome */ 4 -o-tra

不设置宽高,使元素居中的方法

在某些特定的场合,在没有知道宽度的情况下却要求水平居中,今找到些解决方法,现转过来一起学习学习 方案一.利用浮动的包裹性和相对定位百分比数据值特性,传说称之为“相对浮动” .unknow_width_center1 {position:relative; left:50%; float:left;}.unknow_width_center1 li {position:relative; right:50%; z-index:2; float:left}<</span>ul class=&

jQ禁止右键点击、隐藏搜索文本框文字、在新窗口中打开链接、检测浏览器、预加载图片、页面样式切换、所有列等高、动态控制页面字体大小、获得鼠标指针的X值Y值、验证元素是否为空、替换元素、延迟加载、验证元素是否存在于Jquery集合中、使DIV可点击、克隆对象、使元素居中、计算元素个数、使用Google主机上的Jquery类库、禁用Jquery效果、解决Jquery类库与其他Javascript类库冲突

1. 禁止右键点击 代码如下: $(document).ready(function(){ $(document).bind("contextmenu",function(e){ return false; }); }); 2. 隐藏搜索文本框文字 代码如下: $(document).ready(function() { $("input.text1").val("Enter your search text here"); textFill($

【整理】如何使元素水平垂直居中

第一种:已知元素宽.高 兼容:IE6+ 源码: <title>css使元素垂直居中</title> <style type="text/css"> .box{ width: 200px; height: 200px; background-color: grey; /*css使元素垂直居中*/ position: relative; } .box .center{ width: 100px; height: 100px; background-col

css 使元素水平居中

css使元素水平居中 1.对于行内元素的水平居中 给父元素设置text-align:center <div style="text-align:center;">居中显示</div> 2.定宽块状元素水平居中 <div style="width:200px;margin:20px auto;";>居中显示</div> 注:对于以上情况可以灵活应用 可以将元素设置 display:inline ,将其变为行内元素,再按照

使元素相对于窗口或父元素水平垂直居中的几种方法

如果一个元素具有固定或相对大小,要使其不管如何调整窗口大小或滚动页面,始终位于浏览器窗口中间,可使用如下方法: <!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title><meta charset="utf-8&q

CSS 使元素垂直居中

重点内容:负外边距,绝对垂直居中,box 拓展点:设置inline-block,使元素居中 1.实现文字居中对齐 水平居中:text-align:center 垂直居中:设置line-height和height一样 2.实现元素居中对齐 使用元素定位,并移动元素  方法1:负外边距法(兼容IE) 原理:使用绝对定位,定位元素left和top值都为50%:然后使用margin移动负的元素半宽高 条件:需要知道当前元素的宽高. 代码: #content1{ position: relative; w

关于使用绝对定位使元素垂直居中的问题

今天学习中遇到了使元素垂直居中的问题,网上一搜至少有8种不同的方法,我只试了使用绝对定位的方法.这一试不要紧,一试就懵逼了.下面我把我遇到的问题说一下. 我刚开始是这么试的: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> <title>one</title> </head> <style rel="stylesheet&qu

Android-两个小球不停的绕中心旋转的进度条

转载请标明出处: http://blog.csdn.net/hanhailong726188/article/details/47363911 本文出自:海龙的博客 一.概述 最近做了一个比较清新的进度条,没啥难度的,就是涉及到属性动画和canvas绘制圆形的知识,因为群里有一个问怎么实现的,这里就稍微写了一下原理,先看效果图 二.效果图 Gif录制的帧数有点低,导致稍微有点卡,但是在真实运行的时候一点都不卡 三.实现原理 自定义view 自定义属性动画 canvas画圆 四.代码实现 因为代码