实际项目中使用到了这个功能,想着做成一个函数方便日后调用,草草写就,纰漏不少,还是有待完善。目前只能绘制直线和折线。
关于下面那个Object.prototype.extend函数旨在获取一个新对象,不对原有对象进行改变,欢迎赐教。

// JavaScript source code
'use strict';
function dotLine(canvasId, options) {
    function DotLine(canvasId, options) {
        this.options = DotLine.Defaults.extend(options);
        this.Canvas = document.getElementById(canvasId);
        this.Drawer = this.Canvas.getContext('2d');
        this.Drawer.fillStyle = this.options.lineColor;
        this.pointX = this.options.constX;
        this.pointY = this.options.constY;
        this.turns = this.options.turns;

        var stepLength = this.options.stepLen;
        if (this.turns.length) {
            var moveX = stepLength * Math.cos(this.options.direction);
            var moveY = stepLength * Math.sin(this.options.direction);
            var stepNum = this.options.stepNum;
            this.Draw(false, true, moveX, moveY, stepNum);
            this.pointX += moveX * (stepNum - 1);
            this.pointY += moveY * (stepNum - 1);
            for (var turn = 0; turn < this.turns.length; turn++) {
                stepNum = this.turns[turn].stepNum;
                moveX = stepLength * Math.cos(this.turns[turn].direction);
                moveY = stepLength * Math.sin(this.turns[turn].direction);
                this.Draw(false, true, moveX, moveY, stepNum);
                this.pointX += moveX * (stepNum - 1);
                this.pointY += moveY * (stepNum - 1);
            }
        }
        else {
            var moveX = stepLength * Math.cos(this.options.direction);
            var moveY = stepLength * Math.sin(this.options.direction);
            var stepNum = this.options.stepNum;
            this.Draw(false, true, moveX, moveY, stepNum);
        }
    }

    DotLine.Defaults = {
        constX: 3,
        constY: 3,
        stepLen: 30,
        stepNum: 5,
        direction: Math.PI * 0,
        r: 3,
        lineColor: '#000',
        turns: [
            /*{
                stepNum: 0,
                direction: Math.PI * 3/2 // 0 <= direction < Math.PI*2
            }*/
        ]
    };

    DotLine.prototype.Draw = function (pathBegan, closeAfterDrawing, moveX, moveY, stepNum) {
        if (!pathBegan) {
            this.Drawer.beginPath();
        }
        for (var i = 0; i < stepNum; i++) {
            this.Drawer.arc(this.pointX + moveX * i, this.pointY + moveY * i, 3, 0, Math.PI * 2, true);
            this.Drawer.closePath();
            this.Drawer.fill();
            this.Drawer.beginPath();
            }
        if (closeAfterDrawing) {
            this.Drawer.closePath();
        }
    }
    var dotline = new DotLine(canvasId,options);
    return dotline;
}

Object.prototype.extend:

// JavaScript source code
'use strict';
Object.prototype.extend = function (objB) {
    if (typeof this === 'object' && typeof objB === 'object') {
        var destination = {};
        for (var attr in this) {
            destination[attr] = this[attr];
        }
        for (var attr in objB) {
            destination[attr] = objB[attr];
        }
        return destination;
    }
    else {
        var destination = {};
        for (var attr in this) {
            destination[attr] = this[attr];
        }
        return destination;
    }
}