UNPKG

paper

Version:

The Swiss Army Knife of Vector Graphics Scripting

201 lines (187 loc) 6.88 kB
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vektor</title> <link rel="stylesheet" href="../css/style.css"> <script type="text/javascript" src="../../dist/paper-full.js"></script> <script type="text/paperscript" canvas="canvas"> //////////////////////////////////////////////////////////////////////////////// // Interface var values = { fixLength: false, fixAngle: false, showCircle: false, showAngleLength: true, showCoordinates: false }; //////////////////////////////////////////////////////////////////////////////// // Vector var vectorStart, vector, vectorPrevious; var vectorItem, items, dashedItems; function processVector(event, drag) { vector = event.point - vectorStart; if (vectorPrevious) { if (values.fixLength && values.fixAngle) { vector = vectorPrevious; } else if (values.fixLength) { vector.length = vectorPrevious.length; } else if (values.fixAngle) { vector = vector.project(vectorPrevious); } } drawVector(drag); } function drawVector(drag) { if (items) { for (var i = 0, l = items.length; i < l; i++) { items[i].remove(); } } if (vectorItem) vectorItem.remove(); items = []; var arrowVector = vector.normalize(10); var end = vectorStart + vector; vectorItem = new Group( new Path(vectorStart, end), new Path( end + arrowVector.rotate(135), end, end + arrowVector.rotate(-135) ) ); vectorItem.strokeWidth = 0.75; vectorItem.strokeColor = '#e4141b'; // Display: dashedItems = []; // Draw Circle if (values.showCircle) { dashedItems.push(new Path.Circle(vectorStart, vector.length)); } // Draw Labels if (values.showAngleLength) { drawAngle(vectorStart, vector, !drag); if (!drag) drawLength(vectorStart, end, vector.angle < 0 ? -1 : 1, true); } var quadrant = vector.quadrant; if (values.showCoordinates && !drag) { drawLength(vectorStart, vectorStart + [vector.x, 0], [1, 3].indexOf(quadrant) != -1 ? -1 : 1, true, vector.x, 'x: '); drawLength(vectorStart, vectorStart + [0, vector.y], [1, 3].indexOf(quadrant) != -1 ? 1 : -1, true, vector.y, 'y: '); } for (var i = 0, l = dashedItems.length; i < l; i++) { var item = dashedItems[i]; item.strokeColor = 'black'; item.dashArray = [1, 2]; items.push(item); } // Update palette values.x = vector.x; values.y = vector.y; values.length = vector.length; values.angle = vector.angle; } function drawAngle(center, vector, label) { var radius = 25, threshold = 10; if (vector.length < radius + threshold || Math.abs(vector.angle) < 15) return; var from = new Point(radius, 0); var through = from.rotate(vector.angle / 2); var to = from.rotate(vector.angle); var end = center + to; dashedItems.push(new Path.Line(center, center + new Point(radius + threshold, 0))); dashedItems.push(new Path.Arc(center + from, center + through, end)); var arrowVector = to.normalize(7.5).rotate(vector.angle < 0 ? -90 : 90); dashedItems.push(new Path([ end + arrowVector.rotate(135), end, end + arrowVector.rotate(-135) ])); if (label) { // Angle Label var text = new PointText(center + through.normalize(radius + 10) + new Point(0, 3)); text.content = Math.floor(vector.angle * 100) / 100 + '\xb0'; items.push(text); } } function drawLength(from, to, sign, label, value, prefix) { var lengthSize = 5; if ((to - from).length < lengthSize * 4) return; var vector = to - from; var awayVector = vector.normalize(lengthSize).rotate(90 * sign); var upVector = vector.normalize(lengthSize).rotate(45 * sign); var downVector = upVector.rotate(-90 * sign); var lengthVector = vector.normalize( vector.length / 2 - lengthSize * Math.SQRT2); var line = new Path(); line.add(from + awayVector); line.lineBy(upVector); line.lineBy(lengthVector); line.lineBy(upVector); var middle = line.lastSegment.point; line.lineBy(downVector); line.lineBy(lengthVector); line.lineBy(downVector); dashedItems.push(line); if (label) { // Length Label var textAngle = Math.abs(vector.angle) > 90 ? textAngle = 180 + vector.angle : vector.angle; // Label needs to move away by different amounts based on the // vector's quadrant: var away = (sign >= 0 ? [1, 4] : [2, 3]).indexOf(vector.quadrant) != -1 ? 8 : 0; var text = new PointText(middle + awayVector.normalize(away + lengthSize)); text.rotate(textAngle); text.justification = 'center'; value = value || vector.length; text.content = (prefix || '') + Math.floor(value * 1000) / 1000; items.push(text); } } //////////////////////////////////////////////////////////////////////////////// // Mouse Handling var dashItem; function onMouseDown(event) { var end = vectorStart + vector; var create = false; if (event.modifiers.shift && vectorItem) { vectorStart = end; create = true; } else if (vector && (event.modifiers.option || end && end.getDistance(event.point) < 10)) { create = false; } else { vectorStart = event.point; } if (create) { dashItem = vectorItem; vectorItem = null; } processVector(event, true); } function onMouseDrag(event) { if (!event.modifiers.shift && values.fixLength && values.fixAngle) vectorStart = event.point; processVector(event, event.modifiers.shift); } function onMouseUp(event) { processVector(event, false); if (dashItem) { dashItem.dashArray = [1, 2]; dashItem = null; } vectorPrevious = vector; } </script> </head> <body> <canvas id="canvas" resize></canvas> </body> </html>