canvas实现画图板(原型)

效果实现:

源码展示:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>canvas实现画板</title>
<script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<style>
body,html {
	font-size:100%;
	padding:0;
	margin:0;
}
/* Reset */
*,*:after,*:before {
	-webkit-box-sizing:border-box;
	-moz-box-sizing:border-box;
	box-sizing:border-box;
}
.clearfix:before,.clearfix:after {
	content:" ";
	display:table;
}
.clearfix:after {
	clear:both;
}
body {
	background:#494A5F;
	color:#D5D6E2;
	font-weight:500;
	font-size:1.05em;
	font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;
}
a {
	color:#2fa0ec;
	text-decoration:none;
	outline:none;
}
a:hover,a:focus {
	color:#74777b;
}
/*nav*/
button {
	display:inline-block;
	margin:0.5em;
	padding:0.6em 1em;
	border:3px solid #fff;
	font-weight:700;
	background:#1d7db1;
	color:#fff;
}
.center {
	text-align:center;
}
h5 {
	width:100%;
	padding:0;
	margin:0;
	font-size:24px;
	text-align:center;
	height:40px;
	line-height:40px;
}
.sketchpad {
	background:#FFF;
	width:320px;
	height:500px;
	border-radius:2px;
	-webkit-box-shadow:2px 2px 5px 0px rgba(50,50,50,0.75);
	-moz-box-shadow:2px 2px 5px 0px rgba(50,50,50,0.75);
	box-shadow:2px 2px 5px 0px rgba(50,50,50,0.75);
}
.color-line {
	text-align:center;
	height:50px;
	line-height:50px;
}
.color-line input {
	vertical-align:middle;
}
.color-line span {
	font-size:18px;
}
</style>
</head>
<body>
<div id="main_content_wrap" class="outer">
    <section id="main_content" class="inner">
        <h5>画板</h5>
        <div style="text-align: center">
            <canvas class="sketchpad" id="sketchpad"><canvas>
				</canvas></canvas></div>
				<div class="color-line">
					<span>颜色:</span>
					<input id="color-picker" type="color">
					<span>画笔大小:</span>
					<input id="size-picker" type="range" min="1" max="50">
				</div>
		</section>
	</div>
	
	
	<script type="text/javascript">
		// 创建sketchpad面向对象
		var sketchpad;
		$(document).ready(function () {
			sketchpad = new Sketchpad({
				element: '#sketchpad',
				width: 320,
				height: 500,
			});
			$('#color-picker').change(color);//颜色
			$('#color-picker').val('#000');//颜色默认黑色
			$('#size-picker').change(size);//大小
			$('#size-picker').val(1);//大小默认1
		});
		// 颜色
		function color(event) {
			sketchpad.color = $(event.target).val();
		}
		// 大小
		function size(event) {
			sketchpad.penSize = $(event.target).val();
		}
	</script>

<script>
// zhangyibo
// sketchpad.redraw(sketchpad.strokes); // 监听数组变化绘图方法
// this.reset();绘图方法
function Sketchpad(config) {
    for (var key in this.constructor.prototype) {
        this[key] = this[key].bind(this);
    }

    if (!config.hasOwnProperty('element')) {
        console.error('SKETCHPAD ERROR: No element selected');
        return;
    }

    if (typeof(config.element) === 'string') {
        this.element = $(config.element);
    } else {
        this.element = config.element;
    }

    // 宽度
    this._width = config.width || this.element.attr('data-width') || 0;
    // 高度
    this._height = config.height || this.element.attr('data-height') || 0;
    // 颜色
    this.color = config.color || this.element.attr('data-color') || '#000000';
    // 大小
    this.penSize = config.penSize || this.element.attr('data-penSize') || 5;
    // 数组坐标点
    this.strokes = config.strokes || [];
    this._currentStroke = {
        color: null,
        size: null,
        lines: [],
    };


    this.undoHistory = config.undoHistory || [];

    this._sketching = false;
    // 画图
    this.reset();
    this.change();
}

//
// Private API
//
// 监听数组变化
Sketchpad.prototype.change = function(event) {
    Array.prototype._push = Array.prototype.push;
    Array.prototype.push = function(v) {
        this._push(v);
        if (typeof this.pushListener == 'function') this.pushListener.call(this, v)
    }
    // this.strokes= [];
    console.log(this.strokes)
    this.strokes.pushListener = function(v) {
        console.log('数组发生变化');
        console.log(sketchpad.strokes)
        sketchpad.redraw(sketchpad.strokes); // 监听数组变化绘图
    }
};
// 位置
Sketchpad.prototype._cursorPosition = function(event) {
    return {
        x: event.pageX - $(this.canvas).offset().left,
        y: event.pageY - $(this.canvas).offset().top,
    };
};

Sketchpad.prototype._draw = function(start, end, color, size) {
    this._stroke(start, end, color, size, 'source-over');
};

Sketchpad.prototype._erase = function(start, end, color, size) {
    this._stroke(start, end, color, size, 'destination-out');
};

Sketchpad.prototype._stroke = function(start, end, color, size, compositeOperation) {
    this.context.save();
    this.context.lineJoin = 'round';
    this.context.lineCap = 'round';
    this.context.strokeStyle = color;
    this.context.lineWidth = size;
    this.context.globalCompositeOperation = compositeOperation;
    this.context.beginPath();
    this.context.moveTo(start.x, start.y);
    this.context.lineTo(end.x, end.y);
    this.context.closePath();
    this.context.stroke();

    this.context.restore();
};

//
// Callback Handlers
//

Sketchpad.prototype._mouseDown = function(event) {
    this._lastPosition = this._cursorPosition(event);
    this._currentStroke.color = this.color;
    this._currentStroke.size = this.penSize;
    this._currentStroke.lines = [];
    this._sketching = true;
    this.canvas.addEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseUp = function(event) {
    if (this._sketching) {
        this.strokes.push($.extend(true, {}, this._currentStroke));
        this._sketching = false;
    }
    this.canvas.removeEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseMove = function(event) {
    var currentPosition = this._cursorPosition(event);

    this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
    this._currentStroke.lines.push({
        start: $.extend(true, {}, this._lastPosition),
        end: $.extend(true, {}, currentPosition),
    });

    this._lastPosition = currentPosition;
};

Sketchpad.prototype._touchStart = function(event) {
    event.preventDefault();
    if (this._sketching) {
        return;
    }
    this._lastPosition = this._cursorPosition(event.changedTouches[0]);
    this._currentStroke.color = this.color;
    this._currentStroke.size = this.penSize;
    this._currentStroke.lines = [];
    this._sketching = true;
    this.canvas.addEventListener('touchmove', this._touchMove, false);
};

Sketchpad.prototype._touchEnd = function(event) {
    event.preventDefault();
    if (this._sketching) {
        this.strokes.push($.extend(true, {}, this._currentStroke));
        this._sketching = false;
    }
    this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchCancel = function(event) {
    event.preventDefault();
    if (this._sketching) {
        this.strokes.push($.extend(true, {}, this._currentStroke));
        this._sketching = false;
    }
    this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchLeave = function(event) {
    event.preventDefault();
    if (this._sketching) {
        this.strokes.push($.extend(true, {}, this._currentStroke));
        this._sketching = false;
    }
    this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchMove = function(event) {
    event.preventDefault();
    var currentPosition = this._cursorPosition(event.changedTouches[0]);

    this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
    this._currentStroke.lines.push({
        start: $.extend(true, {}, this._lastPosition),
        end: $.extend(true, {}, currentPosition),
    });

    this._lastPosition = currentPosition;
};

//
// Public API
//

Sketchpad.prototype.reset = function() {
    // Set attributes
    this.canvas = this.element[0];
    this.canvas.width = this._width;
    this.canvas.height = this._height;
    this.context = this.canvas.getContext('2d');

    // Setup event listeners
    this.redraw(this.strokes);

    if (this.readOnly) {
        return;
    }

    // Mouse
    this.canvas.addEventListener('mousedown', this._mouseDown);
    this.canvas.addEventListener('mouseout', this._mouseUp);
    this.canvas.addEventListener('mouseup', this._mouseUp);

    // Touch
    this.canvas.addEventListener('touchstart', this._touchStart);
    this.canvas.addEventListener('touchend', this._touchEnd);
    this.canvas.addEventListener('touchcancel', this._touchCancel);
    this.canvas.addEventListener('touchleave', this._touchLeave);
};

Sketchpad.prototype.drawStroke = function(stroke) {
    for (var j = 0; j < stroke.lines.length; j++) {
        var line = stroke.lines[j];
        this._draw(line.start, line.end, stroke.color, stroke.size);
    }
};

Sketchpad.prototype.redraw = function(strokes) {
    for (var i = 0; i < strokes.length; i++) {
        this.drawStroke(strokes[i]);
    }
};

Sketchpad.prototype.toObject = function() {
    return {
        width: this.canvas.width,
        height: this.canvas.height,
        strokes: this.strokes,
        undoHistory: this.undoHistory,
    };
};

Sketchpad.prototype.toJSON = function() {
    return JSON.stringify(this.toObject());
};

Sketchpad.prototype.animate = function(ms, loop, loopDelay) {
    this.clear();
    var delay = ms;
    var callback = null;
    for (var i = 0; i < this.strokes.length; i++) {
        var stroke = this.strokes[i];
        for (var j = 0; j < stroke.lines.length; j++) {
            var line = stroke.lines[j];
            callback = this._draw.bind(this, line.start, line.end,
                stroke.color, stroke.size);
            this.animateIds.push(setTimeout(callback, delay));
            delay += ms;
        }
    }
    if (loop) {
        loopDelay = loopDelay || 0;
        callback = this.animate.bind(this, ms, loop, loopDelay);
        this.animateIds.push(setTimeout(callback, delay + loopDelay));
    }
};

Sketchpad.prototype.cancelAnimation = function() {
    for (var i = 0; i < this.animateIds.length; i++) {
        clearTimeout(this.animateIds[i]);
    }
};

Sketchpad.prototype.clear = function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Sketchpad.prototype.undo = function() {
    this.clear();
    var stroke = this.strokes.pop();
    if (stroke) {
        this.undoHistory.push(stroke);
        this.redraw(this.strokes);
    }
};

Sketchpad.prototype.redo = function() {
    var stroke = this.undoHistory.pop();
    if (stroke) {
        this.strokes.push(stroke);
        this.drawStroke(stroke);
    }
};
</script>

</body>
</html>

 

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值