2014/09/16 – Canvas & Bezier

都是 Canvas.setLineDash 惹的祸,就因为他是草案,所以有些浏览器还不支持。

需求: 画虚线。

分析:线包括直线与曲线。直线的虚线很好实现就不多说了,主要说下曲线的实现,即(3次)贝塞尔曲线的实现。

思路:1. 根据像素粒度值计算出3次贝塞尔曲线的点集合(参考wiki);

   2. 根据求得的点集合,进行虚线的绘制; (难点是根据传入参数 dash list 进行像素点筛选)

code:

var DashedBezier = function (ctx, points, dashList, options) {
            this.ctx = ctx;
            this.points = points;
            this.dashList = dashList;
            this.options = $.extend( {
                particleSize: 100,
                strokeStyle: "#000",
                lineWidth: "1"
            }, options || {});
        };
        DashedBezier.prototype = {
            constructor: DashedBezier,
            _pointOnCubicBezier: function (cp, t) {
                var ax, bx, cx;
                var ay, by, cy;
                var tSquared, tCubed;
                var result = { x: 0.0, y: 0.0 };

                /*計算多項式係數*/

                cx = 3.0 * (cp[1].x - cp[0].x);
                bx = 3.0 * (cp[2].x - cp[1].x) - cx;
                ax = cp[3].x - cp[0].x - cx - bx;

                cy = 3.0 * (cp[1].y - cp[0].y);
                by = 3.0 * (cp[2].y - cp[1].y) - cy;
                ay = cp[3].y - cp[0].y - cy - by;

                /*計算位於參數值t的曲線點*/

                tSquared = t * t;
                tCubed = tSquared * t;

                result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
                result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;

                return result;
            },
            _computeBezier: function (cp, numberOfPoints) {
                var dt;
                var i;
                var curve = [];

                dt = 1.0 / (numberOfPoints - 1);

                for (i = 0; i < numberOfPoints; i++)
                    curve[i] = this._pointOnCubicBezier(cp, i * dt);

                return curve;
            },
            _bezier: function (controlPoints, t) {
                return [controlPoints[t].x, controlPoints[t].y];
            },
            _calculateDashedBezier: function (controlPoints, dashPattern) {
                var step = 1; //this really should be set by an intelligent method,
                //rather than using a constant, but it serves as an
                //example.

                //possibly gratuitous helper functions
                var delta = function (p0, p1) {
                    return [p1[0] - p0[0], p1[1] - p0[1]];
                };
                var arcLength = function (p0, p1) {
                    var d = delta(p0, p1);
                    return Math.sqrt(d[0] * d[0] + d[1] * d[1]);
                };

                var subPaths = [];
                var loc = this._bezier(controlPoints, 0);
                var lastLoc = loc;

                var dashIndex = 0;
                var length = 0;
                var thisPath = [];
                for (var t = step; t < 100; t += step) {
                    loc = this._bezier(controlPoints, t);
                    length += arcLength(lastLoc, loc);
                    lastLoc = loc;

                    //detect when we come to the end of a dash or space
                    if (length >= dashPattern[dashIndex]) {

                        //if we are on a dash, we need to record the path.
                        if (dashIndex % 2 == 0)
                            subPaths.push(thisPath);

                        //go to the next dash or space in the pattern
                        dashIndex = (dashIndex + 1) % dashPattern.length;

                        //clear the arclength and path.
                        thisPath = [];
                        length = 0;
                    }

                    //if we are on a dash and not a space, add a point to the path.
                    if (dashIndex % 2 == 0) {
                        thisPath.push(loc[0], loc[1]);
                    }
                }
                if (thisPath.length > 0)
                    subPaths.push(thisPath);
                return subPaths;
            },
            _pathParts: function (ctx, pathParts) {
                var isMove = false;
                for (var i = 0; i < pathParts.length; i++) {
                    if (pathParts[i].length !== 0) {
                        if (!isMove) {
                            ctx.moveTo(pathParts[i][0], pathParts[i][1]);
                        } else {
                            ctx.lineTo(pathParts[i][0], pathParts[i][1]);
                        }
                        isMove = !isMove;
                    }
                    //var part = pathParts[i];
                    //if (part.length > 0)
                    //    ctx.moveTo(part[0], part[1]);
                    //for (var j = 1; j < part.length / 2; j++) {
                    //    ctx.lineTo(part[2 * j], part[2 * j + 1]);
                    //}
                }
            },
            _drawDashedBezier: function (ctx, controlPoints, dashPattern) {
                var dashes = this._calculateDashedBezier(controlPoints, dashPattern);
                ctx.beginPath();
                ctx.strokeStyle = this.options.strokeStyle;
                ctx.lineWidth = this.options.lineWidth;
                this._pathParts(ctx, dashes);
                ctx.stroke();
            },
            set_Points: function (points) {
                this.points = points;
            },
            draw: function (ctx) {
                ctx && (this.ctx = ctx);
                var cp = [{ x: this.points[0], y: this.points[1] },
                    { x: this.points[2], y: this.points[3] },
                    { x: this.points[4], y: this.points[5] },
                    { x: this.points[6], y: this.points[7] }],
                    curve = this._computeBezier(cp, this.options.particleSize);

                this._drawDashedBezier(this.ctx, curve, this.dashList);
            }
        };

call:

var dashedBezierInstance = new DashedBezier(
            document.getElementById("dashCanvas").getContext("2d"),
            [0, 150, 75, 50, 225, 200, 300, 150],
            [2, 7],
            {
                strokeStyle: "#cc0000"
            });
        dashedBezierInstance.draw();

call main

html:

<canvas width="400" height="300" id="dashCanvas"></canvas>

index.html

时间: 2024-11-12 02:49:12

2014/09/16 – Canvas & Bezier的相关文章

Android基础入门教程——8.3.16 Canvas API详解(Part 1)

Android基础入门教程--8.3.16 Canvas API详解(Part 1) 标签(空格分隔): Android基础入门教程 本节引言: 前面我们花了13小节详细地讲解了Android中Paint类大部分常用的API,本节开始我们来讲解 Canvas(画板)的一些常用API,我们在Android基础入门教程--8.3.1 三个绘图工具类详解 中已经列出了我们可供调用的一些方法,我们分下类: drawXxx方法族:以一定的坐标值在当前画图区域画图,另外图层会叠加, 即后面绘画的图层会覆盖前

12.我们不是在真空里谈软件工程, 软件要运行在硬件芯片上面, 下面看看一个计算机芯片的发展历史: http://perspectives.mvdirona.com/2014/09/august-21-2014-computer-history-museum-presentation/ http://mvdirona.com/jrh/TalksAndPapers/DileepBhandar

电脑芯片的诞生和发展是20世纪最伟大的发明之一,芯片技术决定了计算机升级换代的速度,决定了计算机小型化实现的程度,决定了计算机智能化的程度,决定了计算机普及化的应用深度. 1971年11月15日,英特尔公司推出了第一枚微处理器——4004芯片.这一举措不仅改变了公司的未来,而且对整个工业产生了深远的影响.同年,intel推出了1103DRAM核心内纯. 1974年,英特尔公司推出了划时代的处理器,Intel 8080.采用了复杂的 指令集以及40管脚封装,8080的处理能力大为提高,其功能是80

·记2014.5.16的一件小事

周五,上班. 由于张工有事请假回家,我和曹工留下一起做接口. 我主要负责接口上层交互部分.期间测试code的时候.发现自己图快点做好.忽略了基本的接口数据类型的定义.有在前一晚上图快,粘贴复制没有检查数据类型.导致了第二天调试付出了惨痛的代价. 目前,我是能抓住大方向的,但是在小的细节不重视.没有在这上面摘过跟头.这次早期及时暴露出来是个好事. 之前看过很多细节决定人生的故事,总会幻想自己也能成为一个这样的人.但是实现却给我当头一棒.梦想没有经过现实的打磨只会成为一个幻想,别人口里的一个笑谈.星

2014.08.16『转岗』『该来的,总得面对』

转岗申请的Email总算发出去了,心里长舒一口气,该来的,总得面对. 愿在阿里研究院的未来依然光明. 安全部,提前说再见了. 2014.08.16『转岗』『该来的,总得面对』,布布扣,bubuko.com

2014.06.16任务

周五要提供一份可完成的SIT6000 今天需要做的就是 文件的上传.(服务器上还需要写几个页面,负责显示) 治疗数据的显示处理.图形的显示 2014.06.16 http上传文件还是有问题. 首次上传没问题,第二次出现问题 2014.06.16任务,布布扣,bubuko.com

2014.8.16 if语句

语句 if语句 大体可以分一下几种: 例子: (一)根据月收入判断是否需要缴税 Console.Write("请输入你的月收入(元):"); double money = Convert.ToDouble(Console.ReadLine()); if (money >= 3500) { Console.WriteLine("请交税"); Console.WriteLine("谢谢合作!"); } else { Console.WriteL

ECCV 2014 Results (16 Jun, 2014) 结果已出

Accepted Papers     Title Primary Subject Area ID 3D computer vision 93 UPnP: An optimal O(n) solution to the absolute pose problem with universal applicability 128 Video Registration to SfM Models 168 Image-based 4-d Modeling Using 3-d Change Detect

oracle__学习笔记2014.09.05

oracle学习笔记2014.09.05 测试数据库配置的信息 全局数据库名:xiuhao 系统标识符(SID):xiuhao 服务器参数文件名:c:\oracle\dbs\spfilexiuhao.ora database control URL: http://C-1:5500/em sys以及system解锁 edit 以文本格式打开当前命令/ / 执行当前命令 l [num] 显示缓存区命令 get [file] 把file中的文件加入到缓冲区 c /[str] /[str] 修改当前语

[转载]信息摘录-2014.5.16

2014年快过半了,在这几个月里,微软诸多产品技术的更新陆陆续续的发布,包括 Windows 8.1 更新包,Windows Phone 8.1 developer preview,SQL Server 2014,Visual Studio 2013 update 2,Office for iPad等等.当然不能忘记在中国发布的 Azure 和Office 365.有兴趣看整个2014年还会陆续有哪些新东西上市,可以查看 The 2014 Microsoft Product Roadmap. 对