在two.js中,只提供了svg渲染时的鼠标事件,而canvas和webgl并没有提供,这样就对本人造成了很大的困扰,因此学习了下计算机图形学相关的知识,实现了利用two.js绘图在canvas、svg、webgl渲染方式下,放缩或移动场景,还能使用鼠标对其进行点击交互。

下面先演示下截图:

点击绿色的矩形:

从上面的图可以看出变色了。

下面滚动滚轮及拖动下场景:

同样点击刚刚那个矩形:

还是可以被找到,并且改变颜色。

下面先来说下2d图形中平移和放缩的原理(非常重要,下面的代码实现都需要用到):

平移:

放缩:

放缩+平移:

可见是先放缩,然后再进行平移。

总结下:

a b c
d e f
g h i

其中a为:水平放缩;

其中c为:水平位移;

其中e为:垂直放缩;

其中f为:垂直位移。

下面来看下代码是如何实现的:

在two.js,two对象:

在scene中存在_matrix里面存储了Float32Array(9),这里就对应了上面的3*3矩阵,上面的就是单位矩阵,

1 0 0
0 1 0
0 0 1

当放缩或移动后:

创建这几个矩形的代码:

代码如下:

function createBtn(id, x, y, weight, color) {rect = two.makeRectangle(x, y, 200, 200);rect.noStroke();rect.fill = color;rect.myId = id;map.set(rect, weight);
}
这些rect都存储在map中,如何在:
$stage.bind('mousedown', function(event){isPressed = true;originalPositionX = event.clientX;originalPositionY = event.clientY;let x = event.clientX;let y = event.clientY;let letX = (rect._translation._x / 2 * (two.scene._matrix.elements[0]) + two.scene._matrix.elements[2]);let letY = (rect._translation._y / 2 * (two.scene._matrix.elements[4]) + two.scene._matrix.elements[5]);let letWidth = rect._width * two.scene._matrix.elements[0];let letHeight = rect._height *two.scene._matrix.elements[4];// if(x > letX &&//   y > letY &&//   x < letX + letWidth &&//   y < letY + letHeight// ){////   console.log("find it");// }// console.log("坐标 x=" + x + "  y=" + y);console.log(two);for(let value of map){let xOffset = value[0]._width / 2;let yOffset = value[0]._height / 2;// console.log("xOffset:" + xOffset);// console.log("yOffset:" + yOffset);// console.log(value[0])let letX = ((value[0]._translation._x - xOffset) * (two.scene._matrix.elements[0]) + two.scene._matrix.elements[2]);let letY = ((value[0]._translation._y - yOffset) * (two.scene._matrix.elements[4]) + two.scene._matrix.elements[5]);let letWidth = value[0]._width * two.scene._matrix.elements[0];let letHeight = value[0]._height * two.scene._matrix.elements[4];// console.log("id:" + value[0].myId);// console.log("letX:" + letX + "  letY:" + letY);// console.log("letWidth: " + letWidth + "  letHeight:" + letHeight);// console.log("");if(x > letX &&y > letY &&x < letX + letWidth &&y < letY + letHeight){let r = Math.round(Math.random() * 255);let g = Math.round(Math.random() * 255);let b = Math.round(Math.random() * 255);let rgbStr = "rgb(" + r + "," + g + "," + b + ")";value[0].fill = rgbStr;console.log("find it " + value[0].myId);break;}}// console.log("---------------------------------");});

代码按下时对map进行遍历,如何将其进行转换后的坐标以及宽度进行矩阵变化即可:

这里有一点要说明的two.js中画矩形如果是从200, 200开始,那么这个200,200将会是矩形的

中心点,并不是左上角的点,所以这里有功offset.

鼠标拖动,滚轮放缩相关的代码:

(function(Two){let _ = Two.Utils;let Surface = function(object) {this.object = object;};_.extend(Surface.prototype, {limits: function(min, max) {let min_exists = !_.isUndefined(min);let max_exists = !_.isUndefined(max);if (!max_exists && !min_exists) {return { min: this.min, max: this.max };}this.min = min_exists ? min : this.min;this.max = max_exists ? max : this.max;return this;},apply: function(px, py, s) {this.object.translation.set(px, py);this.object.scale = s;return this;}});let ZUI = Two.ZUI = function(group, domElement) {this.limits = {scale: ZUI.Limit.clone(),x: ZUI.Limit.clone(),y: ZUI.Limit.clone()};this.viewport = domElement || document.body;this.viewportOffset = {matrix: new Two.Matrix()};this.surfaceMatrix = new Two.Matrix();this.surfaces = [];this.reset();this.updateSurface();this.add(new Surface(group));};_.extend(ZUI, {Surface: Surface,Clamp: function(v, min, max) {return Math.min(Math.max(v, min), max);},Limit: {min: -Infinity,max: Infinity,clone: function() {let result = {};for (let k in this) {result[k] = this[k];}return result;}},TranslateMatrix: function(m, x, y) {m.elements[2] += x;m.elements[5] += y;return m;},PositionToScale: function(pos){return Math.exp(pos);},ScaleToPosition: function(scale){return Math.log(scale);}});_.extend(ZUI.prototype, {constructor: ZUI,add: function(surface){this.surfaces.push(surface);let limits = surface.limits();this.addLimits(limits.min, limits.max);return this;},addLimits: function(min, max, type) {type = type || 'scale';if (!_.isUndefined(min)){if(this.limits[type].min){this.limits[type].min = Math.max(min, this.limits[type].min);}else{this.limits[type].min = min;}}if(_.isUndefined(max)){return this;}if(this.limits[type].max){this.limits[type].max = Math.min(max, this.limits[type].max);}else{this.limits[type].max = max;}return this;},clientToSurface: function(x, y) {this.updateOffset();let m = this.surfaceMatrix.inverse();let n = this.viewportOffset.matrix.inverse().multiply(x, y, 1);return m.multiply.apply(m, _.toArray(n));},surfaceToClient: function(v) {this.updateOffset();let vo = this.viewportOffset.matrix.clone();let sm = this.surfaceMatrix.multiply.apply(this.surfaceMatrix, _.toArray(v));return vo.multiply.apply(vo, _.toArray(sm));},graphicMove: function(clientX, clientY){let dx = clientX;let dy = clientY;this.translateSurface(dx, dy);return this;},zoomBy: function(byF, clientX, clientY){let s = ZUI.PositionToScale(this.zoom + byF);this.zoomSet(s, clientX, clientY);return this;},zoomSet: function(zoom, clientX, clientY) {let newScale = this.fitToLimits(zoom);this.zoom = ZUI.ScaleToPosition(newScale);if (newScale === this.scale) {return this;}let sf = this.clientToSurface(clientX, clientY);let scaleBy = newScale / this.scale;this.surfaceMatrix.scale(scaleBy);this.scale = newScale;let c = this.surfaceToClient(sf);let dx = clientX - c.x;let dy = clientY - c.y;this.translateSurface(dx, dy);return this;},translateSurface: function(x, y) {ZUI.TranslateMatrix(this.surfaceMatrix, x, y);this.updateSurface();return this;},updateOffset: function() {let rect = this.viewport.getBoundingClientRect();_.extend(this.viewportOffset, rect);this.viewportOffset.left -= document.body.scrollLeft;this.viewportOffset.top -= document.body.scrollTop;this.viewportOffset.matrix.identity().translate(this.viewportOffset.left, this.viewportOffset.top);return this;},updateSurface: function() {let e = this.surfaceMatrix.elements;for(let i = 0; i < this.surfaces.length; i++){this.surfaces[i].apply(e[2], e[5], e[0]);}return this;},reset: function() {this.zoom = 0;this.scale = 1.0;this.surfaceMatrix.identity();return this;},fitToLimits: function(s) {return ZUI.Clamp(s, this.limits.scale.min, this.limits.scale.max);}});})
((typeof global !== 'undefined' ? global : (this || window)).Two);

整个项目打包下载地址:

https://github.com/fengfanchen/frontUI/tree/master/mouseDemo

计算机图形学Web前端笔记-图形平移放缩原理及实现(two.js鼠标事件适用所有渲染)相关推荐

  1. 计算机图形学Web前端笔记-定位并移动到指定坐标点(two.js理论及实现)

    这里先演示下效果笔记毕竟这是给理论及实践的博文. 当按下回车后 会到场景600,600中画个圆并且浏览器会移动到场景600,600的位置,并且这个位置将会是圆心. 同样,滑动滚轮进行放缩后,还是能进行 ...

  2. 计算机图形学Web前端笔记-浏览器中心点转场景坐标理论及实现(two.js)

    实现的功能是这样的: 输入window.mainPage.flyTo(xxx, xxx) 后会在浏览器中心点画个圆心,使用鼠标及滚轮滚动后. 再次运行: 前一篇博文已经说了3*3变化矩阵实现图形放缩及 ...

  3. 计算机图形学14:三维图形的投影变换

    作者:非妃是公主 专栏:<计算机图形学> 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 文章目录 专栏推 ...

  4. 计算机图形学13:三维图形的几何变换

    作者:非妃是公主 专栏:<计算机图形学> 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 文章目录 专栏推 ...

  5. 计算机图形学 第六章 图形变换

    计算机图形学 第六章 图形变换 这章一般只考一道题(10分左右) 数学基础 (都是线性代数的知识,这里略写) 齐次坐标: 将一个原本是 nnn 维的向量用一个 n+1n+1n+1 维向量来表示 如 ( ...

  6. 计算机图形学 实验3 《图形变换》

    计算机图形学 实验3 <图形变换> 一.实验目的 学习图形的基本几何变换. 二.实验内容 1.投影变换: 2.视口变换: 3.旋转.平移和缩放. 三.实验方法 本次实验将投影变换.视口变换 ...

  7. Web前端 笔记 (21-45)

    Web前端 笔记 (21-45) 21.嵌套列表 1.概念 2.有(无)序列表嵌套 3.定义列表嵌套 22.表格标签 1.种类 2.举例 未加语义化标签 添加语义化标签 23.表格属性 1.常见表格属 ...

  8. 计算机图形学实验报告 裁剪,计算机图形学-实验报告三-图形裁剪算法

    <计算机图形学-实验报告三-图形裁剪算法>由会员分享,可在线阅读,更多相关<计算机图形学-实验报告三-图形裁剪算法(9页珍藏版)>请在人人文库网上搜索. 1.图形裁剪算法1. ...

  9. 计算机图形学基础学习笔记-其一:向量与线性代数

    计算机图形学基础学习笔记-其一:向量与线性代数 前言 计算机图形学概述 向量(矢量) 点乘 叉乘 点乘,叉乘与直角坐标系 矩阵 前言 GAMES101现代计算机图形学入门的学习笔记 正在为TA实习攒作 ...

最新文章

  1. 我怎样才能找到带有Mathematica的Waldo?
  2. 华中科大提出EAT-NAS方法:提升大规模神经模型搜索速度
  3. 【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符
  4. 判断字符串是否以指定字符开头
  5. 13个AJAX验证框架
  6. Android RotateAnimation详解
  7. uniapp背景图片android不显示,uni-app网络图片在app不显示,小程序显示
  8. VS2013 使用QCustomPlot等三方库如何配置
  9. DB,Cache和Redis应用场景分析
  10. C++学习札记(1)
  11. android 模块混淆配置,使用android studio混淆多个模块
  12. html叠加层,JavaScript实现多个重叠层点击切换效果的方法
  13. SQL SERVER 2008 “阻止保存要求重新创建表的更改”
  14. 移动开发的那些事(上)
  15. mfc 固定编辑框输入上限和下限_S7200smart的模拟量输入输出
  16. 置换矩阵的转置为什么和逆矩阵相等?
  17. Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.错误解决
  18. 电子设计教程39:软启动电路-观察浪涌电流
  19. ppt转.exe文件小技巧(超链接含视频)
  20. 高防CDN和BGP高防有哪些区别和优势

热门文章

  1. FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_F
  2. 客户关系管理(第3版) Customer Relationship Management,3 ...
  3. 你真的了解 “开源” 么?请查收【保姆级】开源百科
  4. 5分钟教零基础开发一张驾驶舱(附驾驶舱工具及模板)
  5. 地产遇冷之际,行业竞争加剧,房企如何走出营销低谷,先声夺人?
  6. 5.6亿人没有存款、人均负债13万,大数据揭示负债累累的年轻人
  7. 数据分析菜鸟怒怼面试官却被打脸,只会SQL也敢来面试?
  8. Python能做的事情很多别的编程语言也能做,python将会是昙花一现吗?看看这位程序员怎么说~
  9. 关得紧紧的 FreeEIM飞鸽传书
  10. 关于 Service 设计初步(MSDN节选翻译)