| /*
|
| * Licensed to the Apache Software Foundation (ASF) under one
|
| * or more contributor license agreements. See the NOTICE file
|
| * distributed with this work for additional information
|
| * regarding copyright ownership. The ASF licenses this file
|
| * to you under the Apache License, Version 2.0 (the
|
| * "License"); you may not use this file except in compliance
|
| * with the License. You may obtain a copy of the License at
|
| *
|
| * http://www.apache.org/licenses/LICENSE-2.0
|
| *
|
| * Unless required by applicable law or agreed to in writing,
|
| * software distributed under the License is distributed on an
|
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
| * KIND, either express or implied. See the License for the
|
| * specific language governing permissions and limitations
|
| * under the License.
|
| */ |
|
|
| var canvas, context; |
| var lastPoints = Array(); |
| var mirrorPoints = Array();
|
|
|
| var Controller = {
|
|
|
| red: 255,
|
| green: 255,
|
| blue: 64,
|
|
|
| setRGB: function(r,g,b){
|
| this.red=r;this.green=g;this.blue=b;
|
| },
|
|
|
| fill: function(){
|
| context.fillStyle = "rgb("+this.red+","+this.green+","+this.blue+")";
|
| context.fillRect(0,0,400,300);
|
| },
|
|
|
| init: function(){
|
| this.init_canvas();
|
| }
|
| } |
| |
| Controller.push = function(button){ |
| var buttons = document.getElementsByTagName("button"); |
| for (var i=0;i<buttons.length;i++){ |
| buttons[i].style.border="2px solid black"; |
| } |
| button.style.border="2px solid white"; |
| }
|
|
|
| Controller.init_canvas = function() { |
| //
|
| // Find the canvas element. |
| //
|
| canvas = document.getElementById('imageView');
|
| if (!canvas) {
|
| alert('Error: I cannot find the canvas element!');
|
| return;
|
| }
|
|
|
| if (!canvas.getContext) {
|
| alert('Error: no canvas.getContext!');
|
| return;
|
| }
|
|
|
| canvas.style.cursor="url(images/brush.png),auto";
|
| |
| //
|
| // Get the 2D canvas context. |
| //
|
| context = canvas.getContext('2d');
|
| if (!context) {
|
| alert('Error: failed to getContext!');
|
| return;
|
| }
|
|
|
| // Mask
|
| mask(); |
|
|
| // If IE or OperaMobile
|
| if (typeof canvas.attachEvent !== 'undefined') {
|
| canvas.attachEvent("onmousedown", Controller.startDraw, false);
|
| canvas.attachEvent('onmouseup', Controller.stopDraw, false); |
| canvas.attachEvent("ontouchstart", Controller.startDraw, false); |
| canvas.attachEvent('ontouchstop', Controller.stopDraw, false); |
| canvas.attachEvent('ontouchmove', Controller.drawMouse, false);
|
| }
|
| else {
|
| // Attach the mouse and touch event listeners. |
| canvas.onmousedown = Controller.startDraw; |
| canvas.onmouseup = Controller.stopDraw; |
| |
| canvas.ontouchstart = Controller.startDraw; |
| canvas.ontouchstop = Controller.stopDraw; |
| canvas.ontouchmove = Controller.drawMouse;
|
| }
|
| } |
| |
| |
| // |
| // Start drawing - get the start position, and mirror position on the other side of the image. |
| // |
| Controller.startDraw = function(e) { |
| if (e.touches) { |
| // Touch event |
| for (var i = 1; i <= e.touches.length; i++) { |
| lastPoints[i] = getCoords(e.touches[i - 1]); // Get info for finger #1 |
| mirrorPoints[i] = getCoords(e.touches[i - 1]); // Get info for finger #1 |
| mirrorPoints[i].x = 400-mirrorPoints[i].x |
| } |
| } |
| else { |
| // Mouse event |
| lastPoints[0] = getCoords(e); |
| mirrorPoints[0] = getCoords(e); |
| mirrorPoints[0].x = 400-mirrorPoints[0].x |
| canvas.onmousemove = Controller.drawMouse; |
| } |
| |
| return false; |
| } |
| |
| // |
| // Stop drawing |
| // |
| Controller.stopDraw = function(e) { |
| e.preventDefault(); |
| |
| // |
| // Add a "dab" in cases where there was no move action |
| // |
| Controller.drawMouse(e); |
| |
| canvas.onmousemove = null; |
| } |
| |
| // |
| // Draw |
| // |
| Controller.drawMouse = function(e) { |
| if (e.touches) { |
| // Touch Enabled |
| for (var i = 1; i <= e.touches.length; i++) { |
| var p = getCoords(e.touches[i - 1]); // Get info for finger i |
| lastPoints[i] = paint(lastPoints[i].x, lastPoints[i].y, p.x, p.y); |
| mirrorPoints[i] = paint(mirrorPoints[i].x, mirrorPoints[i].y, 400-p.x, p.y); |
| } |
| } |
| else { |
| // Not touch enabled |
| var p = getCoords(e); |
| lastPoints[0] = paint(lastPoints[0].x, lastPoints[0].y, p.x, p.y); |
| mirrorPoints[0] = paint(mirrorPoints[0].x, mirrorPoints[0].y, 400-p.x, p.y); |
| } |
| context.closePath(); |
| context.beginPath(); |
| |
| return false; |
| } |
| |
| // |
| // Paint on the canvas from the (s)tart to (e)nd |
| // |
| function paint(sX, sY, eX, eY) { |
| context.moveTo(sX, sY); |
| brush(eX,eY); |
| return { x: eX, y: eY }; |
| } |
| |
| // |
| // Get the coordinates for a mouse or touch event |
| // |
| function getCoords(e) { |
| if (e.offsetX) { |
| return { x: e.offsetX, y: e.offsetY }; |
| } |
| else if (e.layerX) { |
| return { x: e.layerX, y: e.layerY }; |
| } |
| else { |
| return { x: e.pageX - canvas.offsetLeft, y: e.pageY - canvas.offsetTop }; |
| } |
| }
|
|
|
| |
| // |
| // Add a brush splodge onto the canvas |
| //
|
| brush = function (x,y) {
|
| var c = context,
|
| D = 15,
|
| D2 = D * 2;
|
| hardness = 30;
|
| opacity = 60;
|
| /*
|
| // add this for IE
|
| if (canvas.attachEvent) {
|
| D = 8;
|
| D2 = D * 2;
|
| }
|
| */
|
| c.globalCompositeOperation = 'source-over';
|
| var r = c.createRadialGradient(x, y, hardness / 100 * D - 1, x, y, D);
|
| r.addColorStop(0, 'rgba('+Controller.red+','+Controller.green+','+Controller.blue+',' + opacity / 100 + ')');
|
| r.addColorStop(0.95, 'rgba('+Controller.red+','+Controller.green+','+Controller.blue+',0)'); // prevent aggregation of semi-opaque pixels
|
| r.addColorStop(1, 'rgba('+Controller.red+','+Controller.green+','+Controller.blue+',0)');
|
| c.fillStyle = r;
|
| c.fillRect(x-D, y-D, D2, D2);
|
| c.globalCompositeOperation = 'source-in';
|
| c.rect(x-D, y-D, D2, D2);
|
| }; |
| |
| // |
| // This is a hack to compensate for the coords being upside down without applying transforms to the whole canvas :-) |
| // |
| curveTo = function(cp1x, cp1y, cp2x, cp2y, x, y){ |
| context.bezierCurveTo(cp1x, 300-cp1y, cp2x, 300-cp2y, x, 300-y); |
| }
|
|
|
| mask = function(){
|
| // the butterfly shape |
| context.save();
|
| context.beginPath();
|
| // if IE - TODO butterfly image is not quite drawn correctly
|
| if (!context.bezierCurveTo) {
|
| context.quadraticCurveTo(80.1783,301.0774,134.5506,273.2636,168.0000,228.0000);
|
| context.quadraticCurveTo(174.6660,215.3346,181.3340,202.6654,188.0000,190.0000);
|
| context.quadraticCurveTo(189.3332,194.9995,190.6668,200.0005,192.0000,205.0000);
|
| context.quadraticCurveTo(171.6442,233.3266,148.4269,261.6911,134.0000,295.0000);
|
| context.quadraticCurveTo(134.3333,295.6666,134.6667,296.3334,135.0000,297.0000);
|
| context.quadraticCurveTo(154.8897,289.3127,174.1114,208.2397,205.0000,207.0000);
|
| context.quadraticCurveTo(206.9998,208.6665,209.0002,210.3335,211.0000,212.0000);
|
| context.quadraticCurveTo(213.8325,219.3365,262.2242,296.0280,265.0000,297.0000);
|
| context.quadraticCurveTo(265.3333,296.3334,265.6667,295.6666,266.0000,295.0000);
|
| context.quadraticCurveTo(253.2034,263.5240,229.7223,229.2060,208.0000,205.0000);
|
| context.quadraticCurveTo(209.3332,199.6672,210.6668,194.3328,212.0000,189.0000);
|
| context.quadraticCurveTo(212.3333,189.0000,212.6667,189.0000,213.0000,189.0000);
|
| context.quadraticCurveTo(213.3333,189.0000,213.6667,189.0000,214.0000,189.0000);
|
| context.quadraticCurveTo(235.4263,260.3326,305.6072,300.4202,400.0000,300.0000);
|
| context.quadraticCurveTo(400.7564,260.7574,381.7836,251.4776,376.0000,221.0000);
|
| context.quadraticCurveTo(372.5464,202.8009,374.9546,182.1234,363.0000,173.0000);
|
| context.quadraticCurveTo(352.5150,164.9982,339.5687,168.3028,325.0000,163.0000);
|
| context.quadraticCurveTo(325.0000,162.6667,325.0000,162.3333,325.0000,162.0000);
|
| context.quadraticCurveTo(349.5033,158.3783,352.2077,130.7042,354.0000,109.0000);
|
| context.quadraticCurveTo(345.9678,103.6550,343.8264,100.1513,338.0000,94.0000);
|
| context.quadraticCurveTo(339.8800,86.6748,343.8295,83.7354,341.0000,77.0000);
|
| context.quadraticCurveTo(336.3338,73.6670,331.6662,70.3330,327.0000,67.0000);
|
| context.quadraticCurveTo(311.5394,39.7644,355.2383,26.7068,341.0000,2.0000);
|
| context.quadraticCurveTo(337.2354,0.8094,333.2949,-0.8581,329.0000,1.0000);
|
| context.quadraticCurveTo(327.6668,1.6666,326.3332,2.3334,325.0000,3.0000);
|
| context.quadraticCurveTo(321.9745,19.4608,323.1224,37.2860,309.0000,43.0000);
|
| context.quadraticCurveTo(294.2036,46.5382,273.9450,34.5515,258.0000,41.0000);
|
| context.quadraticCurveTo(230.1233,52.2740,223.0465,111.1756,212.0000,141.0000);
|
| context.quadraticCurveTo(211.3334,141.0000,210.6666,141.0000,210.0000,141.0000);
|
| context.quadraticCurveTo(208.6668,130.3344,207.3332,119.6656,206.0000,109.0000);
|
| context.quadraticCurveTo(204.0002,107.6668,201.9998,106.3332,200.0000,105.0000);
|
| context.quadraticCurveTo(198.0002,105.9999,195.9998,107.0001,194.0000,108.0000);
|
| context.quadraticCurveTo(192.0002,118.6656,189.9998,129.3344,188.0000,140.0000);
|
| context.quadraticCurveTo(188.0000,139.3334,188.0000,138.6666,188.0000,138.0000);
|
| context.quadraticCurveTo(181.3340,119.3352,174.6660,100.6648,168.0000,82.0000);
|
| context.quadraticCurveTo(166.3335,73.6675,164.6665,65.3325,163.0000,57.0000);
|
| context.quadraticCurveTo(159.6670,55.0002,156.3330,52.9998,153.0000,51.0000);
|
| context.quadraticCurveTo(124.5349,29.4373,115.4563,53.0338,91.0000,43.0000);
|
| context.quadraticCurveTo(75.6567,36.7051,77.4912,12.9952,69.0000,0.0000);
|
| context.quadraticCurveTo(65.3654,0.6436,65.9730,0.4032,64.0000,2.0000);
|
| context.quadraticCurveTo(59.0478,4.2801,58.0846,6.9206,56.0000,12.0000);
|
| context.quadraticCurveTo(58.5748,31.4614,74.0400,36.2547,75.0000,60.0000);
|
| context.quadraticCurveTo(70.0342,69.9436,61.4112,73.0454,56.0000,82.0000);
|
| context.quadraticCurveTo(58.6524,86.5103,60.9126,87.5516,62.0000,94.0000);
|
| context.quadraticCurveTo(58.7903,95.8190,48.1997,106.9635,45.0000,111.0000);
|
| context.quadraticCurveTo(51.2644,140.5583,50.9489,147.1374,74.0000,163.0000);
|
| context.quadraticCurveTo(62.8643,167.3318,49.5220,163.8747,41.0000,170.0000);
|
| context.quadraticCurveTo(25.0144,181.4898,28.4368,204.3249,23.0000,226.0000);
|
| context.quadraticCurveTo(16.0797,253.5891,-0.2461,262.3976,0.0000,300.0000);
|
| }
|
| else{
|
| // IE8 took too long to process this... |
| context.moveTo(0,0);
|
| curveTo(80.1783,301.0774,134.5506,273.2636,168.0000,228.0000);
|
| curveTo(174.6660,215.3346,181.3340,202.6654,188.0000,190.0000);
|
| curveTo(189.3332,194.9995,190.6668,200.0005,192.0000,205.0000);
|
| curveTo(171.6442,233.3266,148.4269,261.6911,134.0000,295.0000);
|
| curveTo(134.3333,295.6666,134.6667,296.3334,135.0000,297.0000);
|
| curveTo(154.8897,289.3127,174.1114,208.2397,205.0000,207.0000);
|
| curveTo(206.9998,208.6665,209.0002,210.3335,211.0000,212.0000);
|
| curveTo(213.8325,219.3365,262.2242,296.0280,265.0000,297.0000);
|
| curveTo(265.3333,296.3334,265.6667,295.6666,266.0000,295.0000);
|
| curveTo(253.2034,263.5240,229.7223,229.2060,208.0000,205.0000);
|
| curveTo(209.3332,199.6672,210.6668,194.3328,212.0000,189.0000);
|
| curveTo(212.3333,189.0000,212.6667,189.0000,213.0000,189.0000);
|
| curveTo(213.3333,189.0000,213.6667,189.0000,214.0000,189.0000);
|
| curveTo(235.4263,260.3326,305.6072,300.4202,400.0000,300.0000);
|
| curveTo(400.7564,260.7574,381.7836,251.4776,376.0000,221.0000);
|
| curveTo(372.5464,202.8009,374.9546,182.1234,363.0000,173.0000);
|
| curveTo(352.5150,164.9982,339.5687,168.3028,325.0000,163.0000);
|
| curveTo(325.0000,162.6667,325.0000,162.3333,325.0000,162.0000);
|
| curveTo(349.5033,158.3783,352.2077,130.7042,354.0000,109.0000);
|
| curveTo(345.9678,103.6550,343.8264,100.1513,338.0000,94.0000);
|
| curveTo(339.8800,86.6748,343.8295,83.7354,341.0000,77.0000);
|
| curveTo(336.3338,73.6670,331.6662,70.3330,327.0000,67.0000);
|
| curveTo(311.5394,39.7644,355.2383,26.7068,341.0000,2.0000);
|
| curveTo(337.2354,0.8094,333.2949,-0.8581,329.0000,1.0000);
|
| curveTo(327.6668,1.6666,326.3332,2.3334,325.0000,3.0000);
|
| curveTo(321.9745,19.4608,323.1224,37.2860,309.0000,43.0000);
|
| curveTo(294.2036,46.5382,273.9450,34.5515,258.0000,41.0000);
|
| curveTo(230.1233,52.2740,223.0465,111.1756,212.0000,141.0000);
|
| curveTo(211.3334,141.0000,210.6666,141.0000,210.0000,141.0000);
|
| curveTo(208.6668,130.3344,207.3332,119.6656,206.0000,109.0000);
|
| curveTo(204.0002,107.6668,201.9998,106.3332,200.0000,105.0000);
|
| curveTo(198.0002,105.9999,195.9998,107.0001,194.0000,108.0000);
|
| curveTo(192.0002,118.6656,189.9998,129.3344,188.0000,140.0000);
|
| curveTo(188.0000,139.3334,188.0000,138.6666,188.0000,138.0000);
|
| curveTo(181.3340,119.3352,174.6660,100.6648,168.0000,82.0000);
|
| curveTo(166.3335,73.6675,164.6665,65.3325,163.0000,57.0000);
|
| curveTo(159.6670,55.0002,156.3330,52.9998,153.0000,51.0000);
|
| curveTo(124.5349,29.4373,115.4563,53.0338,91.0000,43.0000);
|
| curveTo(75.6567,36.7051,77.4912,12.9952,69.0000,0.0000);
|
| curveTo(65.3654,0.6436,65.9730,0.4032,64.0000,2.0000);
|
| curveTo(59.0478,4.2801,58.0846,6.9206,56.0000,12.0000);
|
| curveTo(58.5748,31.4614,74.0400,36.2547,75.0000,60.0000);
|
| curveTo(70.0342,69.9436,61.4112,73.0454,56.0000,82.0000);
|
| curveTo(58.6524,86.5103,60.9126,87.5516,62.0000,94.0000);
|
| curveTo(58.7903,95.8190,48.1997,106.9635,45.0000,111.0000);
|
| curveTo(51.2644,140.5583,50.9489,147.1374,74.0000,163.0000);
|
| curveTo(62.8643,167.3318,49.5220,163.8747,41.0000,170.0000);
|
| curveTo(25.0144,181.4898,28.4368,204.3249,23.0000,226.0000);
|
| curveTo(16.0797,253.5891,-0.2461,262.3976,0.0000,300.0000);
|
| } |
| context.closePath(); |
| context.stroke(); |
| context.fillStyle = "rgb(255,255,255)"; |
| context.fill(); |
| context.clip();
|
| }
|
|
|
|
|
|
|