 |
| Script Coder |
 |
Joined: May 07, 2014 Posts: 4528 Location: Canada
|
I think it looks more interesting to see progression from starting to end.  Here's the new code (along with fix to mouse cursor bug that doesn't draw on right location as well) <html> <script type="text/javascript"> colors = [["1","Blue Green","#199ebd"], ["2","Black","#232323"], ["3","Blue Violet","#7366bd"], ["4","Violet(Purple)","#926eae"], ["5","Green","#1cac78"], ["6","Blue","#1f75fe"], ["7","Yellow Green","#c5e384"], ["8","White","#ededed"], ["9","Yellow","#fce883"], ["10","Carnation Pink","#ffaacc"], ["11","Yellow Orange","#ffb653"], ["12","Red","#ee204d"], ["13","Brown","#b5674d"], ["14","Orange","#ff7538"], ["15","Red Orange","#ff5349"], ["16","Red Violet","#c0448f"], ["17","Gray","#95918c"], ["18","Cerulean","#1dacd6"], ["19","Indigo","#5d76cb"], ["20","Green Yellow","#f0e891"], ["21","Dandelion","#fddb6d"], ["22","Apricot","#fdd9b5"], ["23","Violet Red","#f75394"], ["24","Scarlet","#fc2847"], ["25","Wisteria","#cda4de"], ["26","Sky Blue","#80daeb"], ["27","Cadet Blue","#b0b7c6"], ["28","Timberwolf","#dbd7d2"], ["29","Melon","#fdbcb4"], ["30","Peach","#ffcfab"], ["31","Tan","#faa76c"], ["32","Chestnut","#bc5d58"], ]; var varyColorBy = 20; //value to vary each color by out of 255 (plus or minus this value). changed by textbox input later var canvas,canvas2, ctx,ctx2, flag,canvas1,ctx1 = false, prevX = 0, currX = 0, prevY = 0, currY = 0, dot_flag = false; var color = colors[1][2]; var lineWidth = 2; base = 70; top = 10; function drawcolors(){ ctx1.clearRect(0,0,canvas1.width,canvas1.height) for (var x=0;x<16;x++){ ctx1.fillStyle = colors[x][2]; ctx1.fillRect(x*40,0,40,40); } for (var x=16;x<32;x++){ ctx1.fillStyle = colors[x][2]; ctx1.fillRect((x-16)*40,40,40,40); } ctx1.fillStyle = "rgb(0,0,0)"; ctx1.beginPath(); ctx1.lineTo(640,70); ctx1.lineTo(760,10); ctx1.lineTo(760,70); ctx1.lineTo(640,70); ctx1.closePath(); ctx1.fill(); //draw brush size radius = lineWidth/2.0; ctx1.globalAlpha=0.5; ctx1.beginPath(); ctx1.fillStyle = "red"; ctx1.arc(640+lineWidth*2,70-radius,radius, 0, 2 * Math.PI); ctx1.fill(); ctx1.globalAlpha=1.0; ctx1.globalCompositeOperation = "xor"; ctx1.beginPath(); ctx1.arc(640+lineWidth*2,70-radius,radius, 0, 2 * Math.PI); ctx1.stroke(); ctx1.globalCompositeOperation = "source-over";
//draw brush size with current color ctx1.beginPath(); ctx1.arc(800,40,radius,0,2*Math.PI); ctx1.fillStyle = color; ctx1.fill(); } img = 0; function init() { canvas1 = document.getElementById('canvas'); ctx1 = canvas1.getContext("2d"); canvas1.addEventListener("mousedown", function (e) { choosexy('down', e) }, false);
canvas = document.getElementById('can'); canvas2 = document.getElementById('can2'); canvas3 = document.getElementById('can3');
ctx = canvas.getContext("2d"); ctx2 = canvas2.getContext("2d"); ctx3 = canvas3.getContext("2d"); img = document.getElementById("img"); canvas.width = img.width; canvas.height = img.height; canvas2.width = canvas.width; canvas2.height = canvas.height; canvas3.width = canvas.width; canvas3.height = canvas.height; w = canvas.width; h = canvas.height; ph = document.getElementById('ph'); ph.style.top = parseInt(canvas.height)+100+"px"; canvas2.style.left = parseInt(canvas.width)+10+"px"; canvas3.style.left = (parseInt(canvas.width)+10)*2 + "px";
ctx.lineCap = "round"; ctx2.lineCap = "round"; canvas.addEventListener("mousemove", function (e) { findxy('move', e) }, false); canvas.addEventListener("mousedown", function (e) { findxy('down', e) }, false); canvas.addEventListener("mouseup", function (e) { findxy('up', e) }, false); canvas.addEventListener("mouseout", function (e) { findxy('out', e) }, false); drawcolors(); } strokes = []; multistrokes = []; strokecount = -1; function shuffle_(array) { let currentIndex = array.length, randomIndex; // While there remain elements to shuffle. while (currentIndex != 0) {
// Pick a remaining element. randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--;
// And swap it with the current element. [array[currentIndex], array[randomIndex]] = [ array[randomIndex], array[currentIndex]]; } return array; } function componentToHex(c) { var hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; }
function rgbToHex(r, g, b) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); } function rgbStrToHex(rgbstring){ rgb = rgbstring; //rgb = "rgb(0,128,255)" values = rgb.slice(4,-1).split(','); return rgbToHex(parseInt(values[0]),parseInt(values[1]),parseInt(values[2])); } const hexToRgb = hex => hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i ,(m, r, g, b) => '#' + r + r + g + g + b + b) .substring(1).match(/.{2}/g) .map(x => parseInt(x, 16)); function width_(array){ halfsize = array.length/2.0; currentlw = array[0][5]; c = array[0][4]; currentc = hexToRgb(c); r = parseInt(currentc[0]); g = parseInt(currentc[1]); b = parseInt(currentc[2]); if (document.getElementById('varycheckbox').checked){ //if it's check we vary random within varycolorby range varColorBy = parseInt(document.getElementById('varycolorby').value); r = Math.min(255,Math.max(0,r+Math.random()*varColorBy*2-varColorBy)); g = Math.min(255,Math.max(0,g+Math.random()*varColorBy*2-varColorBy)); b = Math.min(255,Math.max(0,b+Math.random()*varColorBy*2-varColorBy)); } for (var i=0;i<array.length;i++){ angle = (90-Math.abs((halfsize)-i)/(halfsize)*90.0)/360.0*2.0*3.1415; thislw = currentlw * 0.1 + Math.sin(angle)*currentlw*1.0; array[i][5] = thislw; currentc = hexToRgb(c); //document.getElementById('debug').innerHTML += currentc + ","; if (document.getElementById('varywithinstroke').checked){ //if it's check we vary random within varycolorby range r = parseInt(currentc[0]); g = parseInt(currentc[1]); b = parseInt(currentc[2]); varColorBy = parseInt(document.getElementById('varycolorby').value); r = Math.min(255,Math.max(0,r+Math.random()*varColorBy*2-varColorBy)); g = Math.min(255,Math.max(0,g+Math.random()*varColorBy*2-varColorBy)); b = Math.min(255,Math.max(0,b+Math.random()*varColorBy*2-varColorBy)); } maxbrightvalue = Math.max(r,g,b); ubound = (Math.min(maxbrightvalue*1.3,255.0))/maxbrightvalue; lbound = 0.8; fraction = ubound - Math.sin(angle)*(ubound-lbound); thisr = parseInt(r*fraction); thisg = parseInt(g*fraction); thisb = parseInt(b*fraction); array[i][7] = thisr; array[i][8] = thisg; array[i][9] = thisb; } return array; }
function angleOf(cx, cy, ex, ey) {//returns angle in degrees var dy = ey - cy; var dx = ex - cx; var theta = Math.atan2(dy, dx); // range (-PI, PI] //theta *= 180 / Math.PI; // rads to degs, range (-180, 180] //if (theta < 0) theta = 360 + theta; // range [0, 360) return theta; } function strokeShuffle(){ strokes2 = []; lsc = -1; thisstrokes = []; for (var i=0;i<strokes.length;i++){ sc = strokes[i][6]; if (sc!=lsc){ if (thisstrokes.length > 0){ thisstrokes = shuffle_(thisstrokes.slice()); for (var j=0;j<thisstrokes.length;j++){ strokes2.push(thisstrokes[j].slice()); } } thisstrokes = []; lsc = sc; } thisstrokes.push(strokes[i].slice()); } if (thisstrokes.length > 0){ thisstrokes = shuffle_(thisstrokes.slice()); for (var j=0;j<thisstrokes.length;j++){ strokes2.push(thisstrokes[j].slice()); } } return strokes2; } function strokeWidth(strokes){ strokes2 = []; lsc = -1; thisstrokes = []; for (var i=0;i<strokes.length;i++){ sc = strokes[i][6]; if (sc!=lsc || i == 0){ if (thisstrokes.length > 0){ thisstrokes = width_(thisstrokes.slice()); for (var j=0;j<thisstrokes.length;j++){ strokes2.push(thisstrokes[j].slice()); } } thisstrokes = []; lsc = sc; } thisstrokes.push(strokes[i].slice()); } if (thisstrokes.length > 0){ thisstrokes = width_(thisstrokes.slice()); for (var j=0;j<thisstrokes.length;j++){ strokes2.push(thisstrokes[j].slice()); } } return strokes2; } function draw2(){ ctx2.clearRect(0, 0, w, h); for (var s=-1;s<multistrokes.length;s++){ lc = -1; llw = -1; lsc = -1; //strokes2 = strokeWidth(strokes.slice()); if (s==-1){ strokes2 = strokeWidth(strokes.slice()); }else{ strokes2 = strokeWidth(multistrokes[s].slice()); }
for (var i=0;i<strokes2.length;i++){ dx1 = strokes2[i][0]; dy1 = strokes2[i][1]; dx2 = strokes2[i][2]; dy2 = strokes2[i][3]; dc = strokes2[i][4]; lw = strokes2[i][5]; sc = strokes2[i][6]; r = strokes2[i][7]; g = strokes2[i][8]; b = strokes2[i][9]; if (document.getElementById('offsetly').checked){ ox = (dx2-dx1) * (Math.random()*0.4+0.8)/2.0; oy = (dy2-dy1) * (Math.random()*0.4+0.8)/2.0; cx = (dx2+dx1)/2.0; cy = (dy2+dy1)/2.0; dx1 = cx - ox; dy1 = cy - oy; dx2 = cx + ox; dy2 = cy + oy; } //if ((lc != dc) || (llw != lw) ||) { //if it's the first stroke we set lx and ly to start there if (lsc != sc) { //if different stroke count lx = dx1; ly = dy1; lc = dc; llw = lw; lsc = sc; } if (Math.random()>=0.0) { if (document.getElementById('offsetly').checked){ nx = dx2-dx1; ny = dy2-dy1; dx1 = lx; dy1 = ly; dx2 = lx+nx; dy2 = ly+ny; } if (document.getElementById('stroketype').value == "1"){ //regular stroke ctx2.beginPath(); ctx2.moveTo(dx1,dy1); ctx2.lineTo(dx2,dy2); //ctx2.strokeStyle = dc; ctx2.strokeStyle = "rgb("+r+","+g+","+b+")"; ctx2.lineWidth = lw; ctx2.stroke(); ctx2.closePath(); }else if (document.getElementById('stroketype').value == "2"){ //circles ctx2.beginPath(); cx = (dx1+dx2)/2; cy = (dy1+dy1)/2; //ctx2.strokeStyle = dc; ctx2.strokeStyle = "rgb("+r+","+g+","+b+")"; //ctx2.lineWidth = lw; ctx2.lineWidth = Math.max(1.0,lw/10.0); ctx2.arc(cx,cy,lw/2.0,0,Math.PI*2); ctx2.stroke(); ctx2.closePath(); } lx = dx2; ly = dy2; } } } } function draw1(){ ctx.clearRect(0, 0, w, h); for (var i=0;i<strokes.length;i++){ dx1 = strokes[i][0]; dy1 = strokes[i][1]; dx2 = strokes[i][2]; dy2 = strokes[i][3]; dc = strokes[i][4]; lw = strokes[i][5]; sc = strokes[i][6]; ctx.beginPath(); ctx.moveTo(dx1,dy1); ctx.lineTo(dx2,dy2); ctx.strokeStyle = dc; ctx.lineWidth = lw; ctx.stroke(); ctx.closePath(); } if (document.getElementById('reflect').checked){ for (var j=0;j<multistrokes.length;j++){ stroke = multistrokes[j]; for (var i=0;i<stroke.length;i++){ dx1 = stroke[i][0]; dy1 = stroke[i][1]; dx2 = stroke[i][2]; dy2 = stroke[i][3]; dc = stroke[i][4]; lw = stroke[i][5]; sc = stroke[i][6]; ctx.beginPath(); ctx.moveTo(dx1,dy1); ctx.lineTo(dx2,dy2); ctx.strokeStyle = dc; ctx.lineWidth = lw; ctx.stroke(); ctx.closePath(); } } } // ctx.beginPath(); // ctx.moveTo(prevX, prevY); // ctx.lineTo(currX, currY); // ctx.strokeStyle = color; // ctx.lineWidth = lineWidth; // ctx.stroke(); // ctx.closePath(); } function draw3(){ ctx3.globalAlpha = 1.0; ctx3.clearRect(0,0,canvas3.width,canvas3.height); //ctx3.fillStyle= 'white'; //ctx3.fillRect(0,0,canvas3.width,canvas3.height); progression = 0; if (document.getElementById("grid").checked && document.getElementById("progression").checked){ by = parseInt(document.getElementById("byValue").value); progressions = by * by; progression = 1; p = []; //progressions savedstrokes = strokes.slice(); for (var i=1;i<=progressions;i++){ p.push(strokes.slice(0,Math.round(strokes.length/progressions*i))); } } for (var i=1;i<=8;i++){ if (document.getElementById("grid").checked){ size = canvas.width/by; n = 0; for (var y=0;y<by;y++){ for (var x=0;x<by;x++){ if (progression==1){ strokes = p[n].slice(); draw(0); //to calculate multi strokes } n+=1; draw2(); ctx3.globalAlpha = 1.0/i; ctx3.drawImage(canvas2,x*size,y*size,size,size); } } }else{ draw2(); ctx3.globalAlpha = 1.0/i; ctx3.drawImage(canvas2,0,0); } } if (progression==1){ strokes = savedstrokes.slice(); } } function drawCursor(clear = 0){ if (clear == 1){ ctx.clearRect(0,0,canvas.width,canvas.height); //redisplay them all before drawing cursor //ctx.globalAlpha=1.0; //ctx.drawImage(img,0,0,canvas.width,canvas.height); draw1(); ctx.globalAlpha=.5; ctx.drawImage(img,0,0,canvas.width,canvas.height); ctx.globalAlpha=1.0; }
ctx.beginPath(); ctx.arc(currX,currY,lineWidth/2.0,0,Math.PI*2.0); saveLineWith = ctx.lineWidth; ctx.lineWidth = 1; savestrokeStyle = ctx.strokeStyle; ctx.strokeStyle = 'red'; ctx.globalCompositeOperation = "xor"; ctx.stroke(); ctx.globalCompositeOperation = "source-over"; ctx.strokeStyle = savestrokeStyle; ctx.lineWidth = saveLineWith; } mirrors = 6; function reflectthem(mirrors){ mirrors = parseInt(mirrors); reflection = []; mx = canvas.width/2.0; my = canvas.height/2.0; for (var i=0;i<strokes.length;i++){ reflection.push(strokes[i].slice()); reflection[i][0] = mx - (reflection[i][0] - mx); reflection[i][2] = mx - (reflection[i][2] - mx); } multistrokes.push(reflection); incang = 360.0/mirrors/360.0*2*Math.PI; for (var a=1;a<mirrors;a++){ ref = []; for (var i=0;i<strokes.length;i++){ ref.push(strokes[i].slice()); p1angle = angleOf(mx,my,ref[i][0],ref[i][1]); p2angle = angleOf(mx,my,ref[i][2],ref[i][3]); p1radius = ((ref[i][0]-mx)**2+(ref[i][1]-my)**2)**0.5; p2radius = ((ref[i][2]-mx)**2+(ref[i][3]-my)**2)**0.5; newangle1 = p1angle+a*incang; newangle2 = p2angle+a*incang; ref[i][0] = mx + p1radius * Math.cos(newangle1); ref[i][1] = my + p1radius * Math.sin(newangle1); ref[i][2] = mx + p2radius * Math.cos(newangle2); ref[i][3] = my + p2radius * Math.sin(newangle2); } multistrokes.push(ref); ref = []; for (var i=0;i<strokes.length;i++){ ref.push(reflection[i].slice()); p1angle = angleOf(mx,my,ref[i][0],ref[i][1]); p2angle = angleOf(mx,my,ref[i][2],ref[i][3]); p1radius = ((ref[i][0]-mx)**2+(ref[i][1]-my)**2)**0.5; p2radius = ((ref[i][2]-mx)**2+(ref[i][3]-my)**2)**0.5; newangle1 = p1angle+a*incang; newangle2 = p2angle+a*incang; ref[i][0] = mx + p1radius * Math.cos(newangle1); ref[i][1] = my + p1radius * Math.sin(newangle1); ref[i][2] = mx + p2radius * Math.cos(newangle2); ref[i][3] = my + p2radius * Math.sin(newangle2); } multistrokes.push(ref); } } function draw(add = 1) {
// ctx.beginPath(); // ctx.moveTo(prevX, prevY); // ctx.lineTo(currX, currY); // ctx.strokeStyle = color; // ctx.lineWidth = lineWidth; // ctx.stroke(); // ctx.closePath(); if (color.includes("rgb")){color = rgbStrToHex(color); } //always turn it into hex rgbthis = hexToRgb(color); if (add == 1){ strokes.push([prevX,prevY,currX,currY,color,lineWidth,strokecount,rgbthis[0],rgbthis[1],rgbthis[2]]); // save stroke information as we draw } if (document.getElementById('reflect').checked){ multistrokes = []; mirrors = parseInt(document.getElementById('mirrors').value); reflectthem(mirrors); }else{ multistrokes = []; } draw1(); drawCursor();
ctx.globalAlpha=.5; ctx.drawImage(img,0,0,canvas.width,canvas.height); ctx.globalAlpha=1.0; draw2(); }
function erase() { var m = confirm("Want to clear"); if (m) { strokes = []; strokecount = -1; ctx.clearRect(0, 0, w, h); ctx2.clearRect(0, 0, w, h); document.getElementById("canvasimg").style.display = "none"; } } function save() { document.getElementById("canvasimg").style.border = "2px solid"; var dataURL = canvas.toDataURL(); document.getElementById("canvasimg").src = dataURL; document.getElementById("canvasimg").style.display = "inline"; } // function getMousePos(canvas, evt) { // var rect = canvas.getBoundingClientRect(); // return { // x: evt.clientX - rect.left, // y: evt.clientY - rect.top // }; // } function choosexy(res, e) { rect = canvas1.getBoundingClientRect(); if (res == 'down') { prevX = currX; prevY = currY; // currX = e.clientX - canvas1.offsetLeft; // currY = e.clientY - canvas1.offsetTop; currX = e.clientX - rect.left; currY = e.clientY - rect.top; if (currX < 640){ pixel = ctx1.getImageData(currX, currY, 1, 1).data; color = "rgb("+pixel[0]+","+pixel[1]+","+pixel[2]+")"; }else{ lineWidth = (currX - 640)/120 * (60); } drawcolors(); } } function findxy(res, e) { rect = canvas.getBoundingClientRect(); if (res == 'down') { prevX = currX; prevY = currY; // currX = e.clientX - canvas.offsetLeft; // currY = e.clientY - canvas.offsetTop; currX = e.clientX - rect.left; currY = e.clientY - rect.top; flag = true; dot_flag = true; if (dot_flag) { ctx.beginPath(); ctx.fillStyle = color; ctx.fillRect(currX, currY, 2, 2); ctx.closePath();
ctx2.beginPath(); ctx2.fillStyle = color; ctx2.fillRect(currX, currY, 2, 2); ctx2.closePath(); dot_flag = false; } } if (res == 'up' || res == "out") { flag = false; strokecount += 1; //increment stroke count } if (res == 'move') { if (flag) { prevX = currX; prevY = currY; // currX = e.clientX - canvas.offsetLeft; // currY = e.clientY - canvas.offsetTop; currX = e.clientX - rect.left; currY = e.clientY - rect.top; draw(); }else{ // currX = e.clientX - canvas.offsetLeft; // currY = e.clientY - canvas.offsetTop; currX = e.clientX - rect.left; currY = e.clientY - rect.top; drawCursor(1); } } } function animate(){ if (document.getElementById('animate').checked){ draw2(); } } setInterval(animate,100); function loadimage(){ image = document.getElementById("img"); image.onload = function(){ init(); } image.src = document.getElementById('src').value; } function save(){ localStorage.setItem("tracer_strokes", JSON.stringify(strokes)); } function load(){ strokes = JSON.parse(localStorage.getItem("tracer_strokes")); } draw(); </script> <body onload="init()"> <canvas id="canvas" width="840" height="80" style="position:absolute;top:0px;left:0px;border:1px solid"></canvas> <table><tr><td><img src='square.jpg' id='img' width="2000px" style="position:absolute;top:80px;left:0px;border:2px solid;"><canvas id="can" width="1200" height="1200" style="position:absolute;top:80px;left:0px;border:2px solid;"></canvas></td><td><canvas id="can2" width="1200" height="960" style="position:absolute;top:80px;left:1200px;border:2px solid;"></td> <td><canvas id="can3" width="1200" height="960" style="position:absolute;top:80px;left:2400px;border:2px solid;"></td></tr></table><br/> <div id='ph' style="position:absolute;top:1100px;left:0%;"> <input type='submit' value='Clear' onclick='erase()'><br/> <input type='checkbox' id='offsetly' value=''>Offsetly Drawn<br/> <!-- <input type='checkbox' id='shuffle' value=''>Shuffle Stroke Parts<br/> --> <input type="checkbox" id='animate' checked>Continuous Redraws<br/> <input type="checkbox" id='varycheckbox' checked>Vary Color Channels by <input type='text' id='varycolorby' value='50' size=3>/255 - <input type="checkbox" id='varywithinstroke'>Vary Within Strokes<br/> Image location/url:<input type='text' id='src' value='seagull.jpg'><input type='submit' onclick='loadimage()' value='Load Image'><br/> <select id="stroketype"><option value="1" selected>Regular Stroke</option> <option value="2">Circles</option> </select> <input type='checkbox' id='reflect' checked>Reflect <input type='text' id='mirrors' value='6' size=3> Mirrors<br/> <input type='checkbox' id='grid' checked>Grid (of Multiples) of <input type='text' id='byValue' value='4' size=3> n by n Value<br/> <input type='checkbox' id='progression' checked>Show Progression (when in Grid mode)<br/> <input type='submit' value='Redraw Canvas3' onclick='draw3()'><br/> <br/> <input type='submit' value='Save to Local Storage' onclick='save()'><input type='submit' value='Load from Local Storage' onclick='load()'><br/>
<div id='debug'></div> <hr> <div id='donate'> The NSI (not so important) stuff: If you find this js/html useful, feel free to use it but if you make money from it (I ask that <br> you transfer $1 USD per sale to me through Paypal at [email protected]). If you don't use Paypal, then don't worry about it. I understand<br/> that there might be fees so maybe save it until you have more than 10 sales then transfer to me once and minus the fee. I would appreciate<br/> this and maybe even add features in the future to this existing program.<br/><br/> I also ask that you donate $1 per sale to GIMP foundation.<br/><br/> I think it's a fair deal, as there is no risk to you for using it for free as much as you please, and only turn around and donate only when you've made sales.<br/> </div> </div> </body> </html>
_________________ TinT
|
|