【图形处理】如何将一个平面图形按照角度往z轴扭曲?
来源:互联网 发布:与权志龙合照软件 编辑:程序博客网 时间:2024/05/17 03:44
前言
最近希望可以做一个小小的2.5d游戏,里面有一个场景有意思,
当卡丁车往路上跑的时候,路面要显示成:
而原本的图片素材类似于:
这个是很明显需要将平面往z轴扭曲一定角度,但是目前阶段在网上找不到html5 canvas的解决方案,没办法,只好重新操刀用切片法和投影方法来模拟这种图案了。
原理讲解
好吧。。我画了一张图,粗浅表示出肉眼看到的图形经过一定角度按照angle来旋转会出现什么形状,最后其实要求的是一个梯形。
注意,后面的实现我没有计算梯形–因为梯形只有三条边是没办法计算的,我索性按照肉眼高度和原始高度的比例来作为相对处理
demo实现
有了算法和计算过程以后,那么按照切片方式很容易实现的。
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html><html><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/> <meta name="apple-mobile-web-app-capable" content="yes"/> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta content="telephone=no,email=no" name="format-detection"> <meta name="full-screen" content="true"/> <%--竖屏--%> <%--<meta name="screen-orientation" content="portrait"/>--%> <%--横屏--%> <%--<meta name="screen-orientation" content="landscape"/>--%> <meta name="x5-fullscreen" content="true"/> <meta name="360-fullscreen" content="true"/> <style> body{ padding: 0; margin: 0; } </style></head><body><div class=""> <img src="images/forestRoad.jpg" id="image" > <img src="" id="preview"></div><canvas width="600" height="600" id="canvas"></canvas> <script> var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var IMAGE=document.getElementById("image"); var PREVIEW=document.getElementById("preview"); IMAGE.onload=function(){ canvas.widthj=IMAGE.width; canvas.height=IMAGE.height; }// ctx.drawImage(IMAGE); //--这是切片方式来生成图片。--up down left right ,请注意 angle的意思是,angle=0的时候是不需要切片生成图片的,因为angle=0表示从正上方看图片的角度。 //angle=90的是后表示图片刚好垂直于眼神--即是说,这时候眼睛看到的是一条直线--尽量不要用到angle=90的情况。 //--用angle以后就是计算三角形的坐标了。 function transform3dImage(image,segNum,angle) { var tmpCanvas = document.createElement("canvas"); var tmpCtx = tmpCanvas.getContext("2d"); var _img_width = image.naturalWidth; var _img_height = image.naturalHeight; //--计算实际的高度和宽度。 var _real_height = parseInt(_img_height * Math.cos(angle)); //--好了,已经算出了投影过去的高度,那么可以知道投影和原始图形之间的比例。 //--当然,这个比例其实就是cos(angle),就是说,没什么可以计算的, //那么现在可以计算出最小的宽度了。 var _min_width = parseInt(_img_width * Math.cos(angle)); //根据这一个已经可以得到切片相关图形了。 tmpCanvas.width = _img_width; tmpCanvas.height = _real_height;// context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);// 参数值// 参数 描述// img 规定要使用的图像、画布或视频。//sx 可选。开始剪切的 x 坐标位置。//sy 可选。开始剪切的 y 坐标位置。//swidth 可选。被剪切图像的宽度。//sheight 可选。被剪切图像的高度。//x 在画布上放置图像的 x 坐标位置。//y 在画布上放置图像的 y 坐标位置。//width 可选。要使用的图像的宽度。(伸展或缩小图像)//height 可选。要使用的图像的高度。(伸展或缩小图像) var _seg_width = ((_img_width - _min_width) / segNum); var _seg_height = ((_real_height) / segNum); var _src_seg_height = (_img_height) / segNum; console.log("当前图片尺寸:" + _img_width + " x " + _img_height + ", 投影后尺寸:最小宽度:" + _min_width + " 高度:" + _real_height + " 分片尺寸:" + _seg_width + "x" + _seg_height + " 原始图片分片单位高度:" + _src_seg_height); for (var i = 0; i < segNum; i++) { var _drawWidth = _min_width + (i + 1) * _seg_width; _drawWidth = parseInt(_drawWidth); if (_drawWidth > _img_width) { _drawWidth = _img_width; } var _drawHeight = _seg_height; var sx = 0; var sy = parseInt(i * _src_seg_height); var swidth = _img_width; var sheight = parseInt(_img_height / segNum); var dest_x = parseInt(_img_width / 2 - (_drawWidth) / 2); var dest_y = i * _seg_height; console.log(" 分片:" + i + " sx:" + sx + ",sy:" + sy + ",swidth:" + _img_width + ",sheight:" + sheight + ",x:" + dest_x + ",y:" + dest_y + ",drawWidth:" + _drawWidth + ",drawHeight:" + _drawHeight); tmpCtx.drawImage(image, sx, sy, swidth, sheight, dest_x, dest_y, _drawWidth, _drawHeight); } return tmpCanvas; } function _seg1(image,segNum,angle){ var _img_width=image.naturalWidth; var _img_height= image.naturalHeight; //--计算实际的高度和宽度。 var _real_height=parseInt(_img_height*Math.cos(angle)); //--好了,已经算出了投影过去的高度,那么可以知道投影和原始图形之间的比例。 //--当然,这个比例其实就是cos(angle),就是说,没什么可以计算的, //那么现在可以计算出最小的宽度了。 var _min_width=parseInt(_img_width*Math.cos(angle)); //根据这一个已经可以得到切片相关图形了。// context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);// 参数值// 参数 描述// img 规定要使用的图像、画布或视频。//sx 可选。开始剪切的 x 坐标位置。//sy 可选。开始剪切的 y 坐标位置。//swidth 可选。被剪切图像的宽度。//sheight 可选。被剪切图像的高度。//x 在画布上放置图像的 x 坐标位置。//y 在画布上放置图像的 y 坐标位置。//width 可选。要使用的图像的宽度。(伸展或缩小图像)//height 可选。要使用的图像的高度。(伸展或缩小图像) var _seg_width=((_img_width-_min_width)/segNum); var _seg_height=((_real_height)/segNum); var _src_seg_height=(_img_height)/segNum; console.log("当前图片尺寸:"+_img_width+" x "+_img_height+", 投影后尺寸:最小宽度:"+_min_width+" 高度:"+_real_height+" 分片尺寸:"+_seg_width+"x"+_seg_height+" 原始图片分片单位高度:"+_src_seg_height); for(var i=0;i< segNum;i++){ var _drawWidth=_min_width+(i+1)*_seg_width; _drawWidth=parseInt(_drawWidth); if(_drawWidth>_img_width){ _drawWidth=_img_width; } var _drawHeight=_seg_height; var sx=0; var sy=parseInt(i*_src_seg_height); var swidth=_img_width; var sheight=parseInt(_img_height/segNum); var dest_x=parseInt(_img_width/2-(_drawWidth)/2); var dest_y=i*_seg_height; console.log(" 分片:"+i+" sx:"+sx+",sy:"+sy+",swidth:"+_img_width+",sheight:"+sheight+",x:"+dest_x+",y:"+dest_y+",drawWidth:"+_drawWidth+",drawHeight:"+_drawHeight); ctx.drawImage(image,sx,sy,swidth,sheight,dest_x,dest_y,_drawWidth,_drawHeight); } } function draw(segNum,angle){ _seg1(IMAGE,segNum,angle); } function realDraw(segNum,angle){ var _canvas=transform3dImage(IMAGE,segNum,angle); PREVIEW.src=_canvas.toDataURL("image/png"); } </script></body></html>
图片素材就是上面那一张图片啦。
素材图片:
现在分别取角度为60,切片数量为2,3,4,50来看看不同之处。
后续
好了,后面我们将要加上按照不同边来扭曲图形的功能,不一定是底边哦。
0 0
- 【图形处理】如何将一个平面图形按照角度往z轴扭曲?
- 【图形处理】如何将一个平面图形按照角度往z轴扭曲【2】-根据左右上下四个边进行旋转
- 图形处理 使用drawBitmapMesh扭曲图像
- /LGC图形渲染/图像处理系列之扭曲(distort)
- 平面图形布局
- 打印平面图形
- Cinema4D 平面图形建模
- 图形图形处理技术
- HTML5高级编程之图形扭曲
- Canvas 图形(Ru)扭曲(Yao)效果
- Android开发图形处理创建一个图形的拷贝
- 图形处理
- 图形处理
- 图形处理
- 如何将字典的无序key按照A-Z排序
- 面试技巧平面图形题
- 平面图形(二维数组)
- WEBGL学习【二】平面图形
- Java线程(十一):Fork/Join-Java并行计算框架
- 利用log4j+mongodb实现分布式系统中日志统一管理
- block在内存中的分布
- 2、基本运算
- 使用 Elasticsearch ik分词实现同义词搜索
- 【图形处理】如何将一个平面图形按照角度往z轴扭曲?
- 分享一个apns的项目
- 在Windows下使用curl命令
- hadoop I/O笔记
- ZOJ 3747 Attack on Titans
- tf卡数据恢复,手机里tf热插拔造成手机无法识别,TF卡电脑无法读取,提示使用前需要格式化
- Javascript对象中关于setTimeout和setInterval的this介绍
- R Programming Notes
- 有关在 Windows 中进行搜索的高级提示