/** * grafitti.js - 画面上に落書きをする */ function(panel){ var canvas = {}; //イベントを他の要素に取られないように透明のマスクを被せておきます。 var mask = panel.appendChild(document.createElement('div')); mask.style.position = "absolute"; mask.style.left = 0; mask.style.top = 0; mask.style.width = panel.offsetWidth + "px"; mask.style.height = panel.offsetHeight + "px"; mask.style.cursor = "hand"; mask.style.backgroundColor = "#FFFFFF"; mask.style.opacity = 0; mask.style.filter = 'alpha(opacity=0)'; if (document.createElementNS) { //FireFoxのSVG var canvas = panel.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'svg')); canvas.style.position = "absolute"; canvas.style.left = 0; canvas.style.top = 0; canvas.style.width = panel.offsetWidth + 'px'; canvas.style.height = panel.offsetHeight + 'px'; canvas.style.cursor = "hand"; canvas.drawStart = function(evt) { evt = fixEvent(evt); window.status = 'start[' + evt.offsetX + ',' + evt.offsetY + ']'; var s = canvas.shape = canvas.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "polyline")); s.setAttribute('points', evt.offsetX + ',' + evt.offsetY + ' '); s.setAttribute('stroke', 'black'); s.setAttribute('fill', 'none'); s.setAttribute('stroke-width', '5'); s.setAttribute('stroke-linecap', 'round'); panel.onmousemove = canvas.draw; return false; } canvas.draw = function(evt) { evt = fixEvent(evt); window.status = 'draw[' + evt.offsetX + ',' + evt.offsetY + ']'; canvas.shape.setAttribute('points', canvas.shape.getAttribute('points') + ' ' + evt.offsetX + ',' + evt.offsetY + ' '); return false; } canvas.drawEnd = function(evt) { if (!panel.onmousemove) return; evt = fixEvent(evt); window.status = 'end[' + evt.offsetX + ',' + evt.offsetY + ']'; panel.onmousemove = null; } } else if (document.namespaces) { //IEのVML var left = 0, top = 0; var p = panel; while (p) { left += p.offsetLeft; top += p.offsetTop; p = p.offsetParent; } if (!document.namespaces.v) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); document.createStyleSheet().addRule("v\\:*", "behavior: url(#default#VML);"); } canvas = panel.appendChild(mask.cloneNode()); canvas.style.backgroundColor = 'transparent'; canvas.style.filter = ''; canvas.drawStart = function(evt) { evt = fixEvent(evt); window.defaultStatus = 'start[' + evt.offsetX + ',' + evt.offsetY + ']'; //v:shapeで線の先端の形状を指定する方法がわからないので、ちょっと角ばってしまいます。 var s = canvas.shape = document.createElement('v:shape'); s.style.position = 'absolute'; s.style.left = left + 'px'; s.style.top = top + 'px'; s.style.width = canvas.offsetWidth + 'px'; s.style.height = canvas.offsetHeight + 'px'; s.setAttribute('strokeweight', 5); s.setAttribute('strokecolor', 'black'); s.setAttribute('filled', 'false'); s.setAttribute('path', 'm ' + evt.offsetX + ',' + evt.offsetY); s.setAttribute('coordsize', canvas.offsetWidth + ',' + canvas.offsetHeight); s.onmousemove = function(evt) { evt = fixEvent(); return false; } canvas.appendChild(s); canvas.onmousemove = canvas.draw; return false; } canvas.draw = function(evt) { evt = fixEvent(evt); window.defaultStatus = 'draw[' + evt.offsetX + ',' + evt.offsetY + ']'; var s = canvas.shape; s.path.value = s.path.value.replace(/ e$/, '') + ' l ' + evt.offsetX + ',' + evt.offsetY + ' e'; return false; } canvas.drawEnd = function(evt) { if (!canvas.onmousemove) return; evt = fixEvent(evt); window.status = 'end[' + evt.offsetX + ',' + evt.offsetY + ']'; canvas.onmousemove = null; return false; } } else { //HTMLのCanvas var canvas = document.createElement('canvas'); canvas.setAttribute('width', panel.clientWidth + 'px'); canvas.setAttribute('height', panel.clientHeight + 'px'); canvas.style.position = "absolute"; canvas.style.left = 0; canvas.style.top = 0; canvas.style.cursor = "hand"; panel.appendChild(canvas); canvas.drawStart = function(evt) { evt = fixEvent(evt); window.status = 'start[' + evt.offsetX + ',' + evt.offsetY + ']'; var ctx = canvas.getContext('2d'); ctx.lineWidth = 5; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(evt.offsetX, evt.offsetY); panel.onmousemove = canvas.draw; } canvas.draw = function(evt) { evt = fixEvent(evt); window.status = 'draw[' + evt.offsetX + ',' + evt.offsetY + ']'; var ctx = canvas.getContext('2d'); ctx.lineTo(evt.offsetX, evt.offsetY); ctx.stroke(); } canvas.drawEnd = function(evt) { if (!canvas.onmousemove) return; evt = fixEvent(evt); window.status = 'end[' + evt.offsetX + ',' + evt.offsetY + ']'; panel.onmousemove = null; } } panel.onmousedown = canvas.drawStart; document.onmouseup = canvas.drawEnd; document.onkeypress = function(evt) { panel.onmousedown = null; document.onmouseup = null; document.onkeypress = null; document.onmousemove = null; panel.removeChild(canvas); panel.removeChild(mask); } //以下のコードは http://shorindo.com/research:1308704774 からの切り貼りで、本質ではありません。 //ただし、offsetXXの値を持たないsvg要素に対応するために改変しています。 var fixEvent = function(evt) { if (!window.event) { if (typeof evt.offsetX != 'number') { //not safari evt.offsetX = evt.pageX; evt.offsetY = evt.pageY; var el = evt.target; while (el) { evt.offsetX -= el.offsetLeft ? el.offsetLeft : 0; evt.offsetY -= el.offsetTop ? el.offsetTop : 0; el = el.offsetParent ? el.offsetParent : el.parentNode; } } } else { evt = window.event; evt.target = evt.srcElement; evt.preventDefault = function() { this.returnValue = false; }; evt.stopPropagation = function() { this.cancelBubble = true; }; switch(evt.type) { case 'click': case 'mousedown': case 'mouseup': case 'mousemove': evt.which = evt.button==4 ? 3 : evt.button; if (document.compatMode == 'CSS1Compat') { evt.pageX = evt.clientX + document.documentElement.scrollLeft; evt.pageY = evt.clientY + document.documentElement.scrollTop; } else { evt.pageX = evt.clientX + document.body.scrollLeft; evt.pageY = evt.clientY + document.body.scrollTop; } break; } } evt.preventDefault(); evt.stopPropagation(); evt.returnValue = false; return evt; } }