前回つくったもの にマウスのスピードに応じてLineの太さを変更する機能を追加しました。
Canvasで落書き 2.1.0 - みかづきブログ その3
マウスをすばやく動かしたときほどLineが細くなります。
DEMO
JavaScript
Point.js
(function(win, doc, ns) { "use strict"; // インスタンスをつくる際にサイズを渡せるように変更 function Point(x, y, opt_size) { var _this = this; _init(); function _init() { ns.EventDispatcher.call(_this); } _this.x = x; _this.y = y; _this.size = opt_size || 1; } Point.prototype = new ns.EventDispatcher(); Point.prototype.constructor = Point; Point.prototype.setSize = function(size) { var _this = this; _this.size = size; }; Point.prototype.draw = function(ctx, opt_size) { var _this = this, size = opt_size || _this.size || 1; ctx.save(); ctx.beginPath(); ctx.arc(_this.x, _this.y, size, 0, Math.PI * 2, false); ctx.fill(); ctx.moveTo(_this.x, _this.y); ctx.restore(); return _this; }; // 2つのPointの距離を返すクラスメソッドを追加 Point.getDistance = function(pointA, pointB) { return Math.sqrt(Math.pow(pointB.x - pointA.x, 2) + Math.pow(pointB.y - pointA.y, 2)); }; ns.Point = Point; })(this, document, App);
Line.js
(function(win, doc, ns) { "use strict"; var Point = ns.Point; function Line(opt_point) { var _this = this, pointList = []; _init(); function _init() { ns.EventDispatcher.call(_this); _this.pointList = pointList; if (opt_point) { _this.push(opt_point); } } } Line.prototype = new ns.EventDispatcher(); Line.prototype.constructor = Line; Line.prototype.push = function(pointModel) { var _this = this; _this.pointList.push(pointModel); }; Line.prototype.drawLine = function(ctx) { var _this = this, pointList = _this.pointList, length = pointList.length, i; ctx.save(); ctx.lineCap = "round"; ctx.lineJoin = "round"; if (length > 1) { for (i = 1; i < length; ++i) { ctx.beginPath(); ctx.moveTo(pointList[i - 1].x, pointList[i - 1].y); ctx.lineTo(pointList[i].x, pointList[i].y); ctx.lineWidth = pointList[i].size; // lineWidthを設定できるように変更 ctx.stroke(); } } else { pointList[0].draw(ctx); } ctx.restore(); }; Line.prototype.drawQuadraticCurve = function(ctx) { var _this = this, pointList = _this.pointList, length = pointList.length, quadraticPointList = [], lastIndex = 0, i; ctx.save(); ctx.lineCap = "round"; ctx.lineJoin = "round"; if (length > 1) { quadraticPointList[lastIndex] = pointList[0]; ctx.beginPath(); ctx.moveTo(quadraticPointList[0].x, quadraticPointList[0].y); for (i = 1; i < length; ++i) { quadraticPointList[++lastIndex] = new Point( (quadraticPointList[lastIndex - 1].x + pointList[i].x) / 2, (quadraticPointList[lastIndex - 1].y + pointList[i].y) / 2 ); quadraticPointList[++lastIndex] = (pointList[i]); ctx.quadraticCurveTo( quadraticPointList[i * 2 - 2].x, quadraticPointList[i * 2 - 2].y, quadraticPointList[i * 2 - 1].x, quadraticPointList[i * 2 - 1].y ); ctx.lineWidth = pointList[i].size; // lineWidthを設定できるように変更 ctx.stroke(); ctx.beginPath(); ctx.moveTo(quadraticPointList[i * 2 - 1].x, quadraticPointList[i * 2 - 1].y); } ctx.lineTo(quadraticPointList[lastIndex].x, quadraticPointList[lastIndex].y); ctx.stroke(); } else { pointList[lastIndex].draw(ctx); } ctx.restore(); }; ns.Line = Line; })(this, document, App);
main.js
(function(win, doc, ns) { "use strict"; var SIZE = 10, _getAve = _buildGetAve(10); function _buildGetAve(opt_maxLength) { var index = 0, array = [], maxLength = opt_maxLength || 10; function _ave() { var length = array.length, sum = 0, i; for (i = 0; i < length; ++i) { sum += array[i]; } return sum / length; } function getAve(val) { array[index] = val; index = (index + 1) % maxLength; return _ave(); } return getAve; } // 2点間の距離からポイントのサイズを割り出す関数を追加 function _getSize(l) { var MAX_DISTANCE = 100, width; if (l > MAX_DISTANCE) { width = 1; } else { width = (MAX_DISTANCE - l) * SIZE / MAX_DISTANCE; } _getAve(width); return _getAve(width); } var ticker = new ns.Ticker(60), lineManager = ns.LineManager.getInstance(), canvas = doc.getElementById("canvas"), ctx = canvas.getContext("2d"), fps = doc.getElementById("fps"), START_EVENT = "mousedown", MOVE_EVENT = "mousemove", END_EVENT = "mouseup"; setup(); function setup() { addSketchEventForCanvas(canvas); ticker.addEventListener("tick", function(evt) { fps.innerHTML = evt.measuredFPS; update(evt.delta); draw(); }); ticker.start(); } function update(delta) { } function draw() { canvas.width = win.innerWidth; canvas.height = win.innerHeight; ctx.save(); ctx.fillStyle = ctx.strokeStyle = "rgba(0, 0, 255, 1)"; lineManager.drawQuadraticCurve(ctx); ctx.restore(); } function addSketchEventForCanvas(elm) { var throttle = new ns.Throttle(10, handleThrottleMoveEvent), ctx = elm.getContext("2d"), positionList = [], lastPoint = null, index = 0; elm.addEventListener(START_EVENT, handleStartEvent, false); doc.addEventListener(END_EVENT, handleEndEvent, false); function handleThrottleMoveEvent(evt) { var currentPoint = new ns.Point(evt.offsetX, evt.offsetY); currentPoint.setSize(_getSize(ns.Point.getDistance(lastPoint, currentPoint))); lastPoint = currentPoint; lineManager.addPoint(currentPoint); } function handleStartEvent(evt) { lastPoint = new ns.Point(evt.offsetX, evt.offsetY, SIZE / 2); lineManager.push(new ns.Line(lastPoint)); elm.addEventListener(MOVE_EVENT, handleMoveEvent, false); } function handleMoveEvent(evt) { throttle.fireEvent(evt); } function handleEndEvent(evt) { elm.removeEventListener(MOVE_EVENT, handleMoveEvent, false); lastPoint = null; } } })(this, document, App);
以上、こんなかんじになりました。