マウスの最初から最後まで線を引く方法を探しています。たとえば、DIV があり、マウスを円形に動かしました。しかし、マウスが移動したパスに線が描画されるようにします。
HTML5 ソリューションを探しているわけではありません。最新のすべてのブラウザーでも機能するようにしたい。
これについて私を助けてください。
マウスの最初から最後まで線を引く方法を探しています。たとえば、DIV があり、マウスを円形に動かしました。しかし、マウスが移動したパスに線が描画されるようにします。
HTML5 ソリューションを探しているわけではありません。最新のすべてのブラウザーでも機能するようにしたい。
これについて私を助けてください。
最新のすべてのブラウザで動作させたい場合は、HTML5 を使用してください
古いブラウザをサポートしたい場合は、http://raphaeljs.com/ JS ライブラリを使用できます。
Raphael は、利用可能な場合は SVG を使用し、利用できない場合は VML を使用します。IE8以下を除く基本的にすべてのブラウザはSVGを使用します。
私は 8 年前に何かを書き、6 年前に改訂し、現在もチェックしていますが、まだ機能しています。画面の2点をクリックして線を描いていますが、ちょっとした工夫でマウス移動に変更できます。
これは純粋な JavaScript であり、基本的にピクセル サイズの画像をドキュメントに追加します。
ここではコードをそのまま書きます。それは本当に古く、作業中はベストプラクティスではない可能性があることに注意してください。
var PIXEL_PATH="http://i.stack.imgur.com/QXTrN.gif";
var ST_LINE=1;
var ST_CIRCLE=2;
var strImageData="";
var strUserInput="";
var strImageName="";
var iPointsCount=0;
var iNumCalls=0;
var loadComplete=false;
var arrLines=new Array();
var arrRedo=new Array();
var strPoints="";
var arrImages;
var objWin;
var INFINITY=-999999;
var iLastX=INFINITY, iLastY=INFINITY;
var drawStyle=ST_LINE;
var arrPoints=new Array();
var iCurrentImage=0;
var blnLineFinished=true;
var blnLoading=true;
var strCurrentPoints="";
document.onclick = DocumentClick;
document.onkeyup = DocumentKeyup;
self.onload=Init;
function Init()
{
DrawPoint(0, 0);
CommitDraw();
}
function DrawImage()
{
var x1, x2, y1, y2;
var iStep=12;
blnLoading = true;
for (j=0; j<document.images.length; j++)
document.images[j].style.visibility = "hidden";
if (objWin)
objWin.close();
arrLines = new Array();
arrRedo = new Array();
document.forms[0].redo.disabled = true;
iLastX=INFINITY;
iLastY=INFINITY;
DrawPoint(0, 0);
CommitDraw();
if ((strImageData.length % 12) != 0)
iStep = 13;
for (i=0; i<strImageData.length; i+=iStep)
{
drawStyle = (iStep == 12)?ST_LINE:ToNumber(strImageData.substr(i, 1));
x1 = ToNumber(strImageData.substr(i+iStep-12, 3));
y1 = ToNumber(strImageData.substr(i+iStep-12+3, 3));
x2 = ToNumber(strImageData.substr(i+iStep-12+6, 3));
y2 = ToNumber(strImageData.substr(i+iStep-12+9, 3));
Line(x1, y1, x2, y2);
}
return true;
}
function Random()
{
event.cancelBubble = true;
var x1, x2, x1_old;
var y1, y2, y1_old;
var z=0;
if (drawStyle == ST_CIRCLE)
{
x1=Rnd(document.body.clientWidth-100)+100;
y1=Rnd(document.body.clientHeight-100)+100;
x2 = x1+MIN(ABS(x1-100), ABS(document.body.clientWidth-100-x1));
y2 = y1+MIN(ABS(y1-100), ABS(document.body.clientHeight-100-y1));
x1_old = x1;
y1_old = y1;
while ((R(x1, y1, x2, y2) >= ABS(x2-x1_old)) || (R(x1, y1, x2, y2) >= ABS(y2-y1_old)))
{
x1 += (ABS(x1-100) > ABS(document.body.clientWidth-100-x1))?-1:1;
y1 += (ABS(y1-100) > ABS(document.body.clientHeight-100-y1))?-1:1;
z++;
if (z >= 100)
break;
}
}
else
{
x1=Rnd(document.body.clientWidth-30)+30;
y1=Rnd(document.body.clientHeight-30)+30;
x2=Rnd(document.body.clientWidth-30)+30;
y2=Rnd(document.body.clientHeight-30)+30;
}
ClearLastPoint();
Line(x1, y1, x2, y2);
arrRedo = new Array();
document.forms[0].redo.disabled = true;
return true;
}
function ToNumber(str) {return (str*(-1)*(-1));}
function Rnd(num) {return parseInt(Math.random()*num);}
function DocumentClick()
{
var iCurX=window.event.x, iCurY=window.event.y;
// blnLoading=false;
if ((iLastX != INFINITY )&&(iLastY != INFINITY))
{
Line(iLastX, iLastY, iCurX, iCurY);
if (drawStyle != ST_CIRCLE)
{iLastX = iCurX; iLastY = iCurY;}
}
else
{
iLastX = iCurX;
iLastY = iCurY;
}
arrRedo = new Array();
document.forms[0].redo.disabled = true;
return true;
}
function DocumentKeyup()
{
if (document.forms[0].all("load"))
return false;
strUserInput += String.fromCharCode(self.event.keyCode);
if (strUserInput.toLowerCase().indexOf("shadow")>=0)
{
var objInput=document.createElement("INPUT");
objInput.name = objInput.id = "load";
objInput.type = "button";
objInput.value = "Load";
objInput.onclick = Load;
document.forms[0].appendChild(objInput);
return true;
}
if (strUserInput.length > 999)
strUserInput.length = "";
return false
}
function Line(x1, y1, x2, y2)
{
arrLines[arrLines.length] = drawStyle+AddZeros(x1, 3)+AddZeros(y1, 3)+
AddZeros(x2, 3)+AddZeros(y2, 3);
blnLineFinished = false;
strCurrentPoints = "";
document.forms[0].undo.disabled = false;
arrPoints = new Array();
iCurrentImage = 0;
if (!blnLoading)
{
divMsg.style.visibility = "visible";
divMsg.style.left = x1+"px";
divMsg.style.top = y1+"px";
}
arrImages=new Array();
if (drawStyle == ST_CIRCLE)
return Circle(x1, y1, x2, y2);
if (x1 == x2)
{
for (y=MIN(y1, y2); y<=MAX(y1, y2); y++)
DrawPoint(x1, y);
return EndLine();
}
if (ABS((x2-x1))>=ABS((y2-y1)))
{
for (x=MIN(x1, x2); x<=MAX(x1, x2); x++)
DrawPoint(x, Y(x, x1, y1, x2, y2));
return EndLine();
}
else
{
for (y=MIN(y1, y2); y<=MAX(y1, y2); y++)
DrawPoint(X(y, x1, y1, x2, y2), y);
return EndLine();
}
}
function Circle(x1, y1, x2, y2)
{
var y, x, r=R(x1, y1, x2, y2);
var iFirst=(x1-r);
var iLast=(x1+r);
var iFirst2=(y1-r);
var iLast2=(y1+r);
for (x=iFirst; x<=iLast; x++)
{
y = Y2(r, x, x1, y1);
DrawPoint(X2(r, y, x1, y1), y);
DrawPoint(X3(r, y, x1, y1), y);
y = Y3(r, x, x1, y1);
DrawPoint(X2(r, y, x1, y1), y);
DrawPoint(X3(r, y, x1, y1), y);
}
for (y=iFirst2; y<=iLast2; y++)
{
x = X2(r, y, x1, y1);
DrawPoint(x, Y2(r, x, x1, y1));
DrawPoint(x, Y3(r, x, x1, y1));
x = X3(r, y, x1, y1);
DrawPoint(x, Y2(r, x, x1, y1));
DrawPoint(x, Y3(r, x, x1, y1));
}
iLastX=INFINITY;
iLastY=INFINITY;
return EndLine();
}
function R(x1, y1, x2, y2)
{
return Math.sqrt(((x2-x1)*(x2-x1))+((y2-y1)*(y2-y1)));
}
function EndLine()
{
CommitDraw();
strPoints = strPoints.substr(0, strPoints.length-1)+"|";
HideMessage();
if (!blnLoading)
divPointsCount.innerHTML = "0";
}
function HideMessage()
{
if (blnLineFinished)
{
divMsg.style.visibility = "hidden"; return true;
}
setTimeout("HideMessage();", 100);
}
function Y(x, x1, y1, x2, y2)
{
return (((y2-y1)/(x2-x1))*(x-x1))+y1;
}
function X(y, x1, y1, x2, y2)
{
return (((x2-x1)/(y2-y1))*(y-y1))+x1;
}
function Y2(r, x, x0, y0)
{
return (y0+Math.sqrt(ABS((r*r)-((x-x0)*(x-x0)))));
}
function X2(r, y, x0, y0)
{
return (x0+Math.sqrt(ABS((r*r)-((y-y0)*(y-y0)))));
}
function Y3(r, x, x0, y0)
{
return (y0-Math.sqrt(ABS((r*r)-((x-x0)*(x-x0)))));
}
function X3(r, y, x0, y0)
{
return (x0-Math.sqrt(ABS((r*r)-((y-y0)*(y-y0)))));
}
function ABS(n) {return (n>=0)?n:(n*-1);}
function MAX(a1, a2) {return (a1>=a2)?a1:a2;}
function MIN(a1, a2) {return (a1<=a2)?a1:a2;}
function AddZeros(iNumber, iZeros)
{
var strZeros="";
for (j=0; j<iZeros; j++)
strZeros += "0";
return (strZeros.substr(0, iZeros-(iNumber+"").length)+iNumber+"");
}
function DrawPoint(x, y)
{
if (PointExists(parseInt(x), parseInt(y)))
return false;
iPointsCount++;
var objImage=document.createElement("IMG");
objImage.id = "i"+iPointsCount;
objImage.name = "i"+iPointsCount;
objImage.src = PIXEL_PATH;
objImage.width = objImage.height = 1;
objImage.border = 0;
objImage.style.position = "absolute";
objImage.style.top = parseInt(y)+"px";
objImage.style.left = parseInt(x)+"px";
strCurrentPoints += parseInt(x)+","+parseInt(y)+"|";
arrPoints[arrPoints.length] = objImage;
// document.body.appendChild(objImage);
strPoints += "i"+iPointsCount+",";
return true;
}
function CommitDraw()
{
if (iCurrentImage >= arrPoints.length)
{
blnLineFinished = true; return true;
}
if (blnLoading)
{
for (iCurrentImage=0; iCurrentImage<arrPoints.length; iCurrentImage++)
document.body.appendChild(arrPoints[iCurrentImage]);
blnLineFinished = true;
}
else
{
document.body.appendChild(arrPoints[iCurrentImage]);
iCurrentImage++;
divPointsCount.innerHTML = (parseInt(divPointsCount.innerHTML)+1)+"";
setTimeout("CommitDraw();", 1);
}
}
function PointExists(x, y)
{
return (strCurrentPoints.indexOf(parseInt(x)+","+parseInt(y)+"|")>=0);
}
function GetImageData()
{
var strAns="";
for (k=0; k<arrLines.length; k++)
strAns += arrLines[k];
return strAns;
}
function Undo()
{
event.cancelBubble=true;
if (arrLines.length>0)
ClearLastLine();
arrRedo[arrRedo.length] = arrLines[arrLines.length-1];
document.forms[0].redo.disabled = false;
var arrTemp=new Array();
for (i=0; i<arrLines.length-1; i++)
arrTemp[i] = arrLines[i];
arrLines = arrTemp;
document.forms[0].undo.disabled = (arrLines.length == 0);
if ((drawStyle == ST_CIRCLE)||(arrLines.length == 0))
{
iLastX=INFINITY;
iLastY=INFINITY;
}
else
{
iLastX=parseInt(document.getElementById("i"+iPointsCount).style.left);
iLastY=parseInt(document.getElementById("i"+iPointsCount).style.top);
}
}
function Redo()
{
event.cancelBubble=true;
if (arrRedo.length == 0)
return false;
var strLine=arrRedo[arrRedo.length-1];
drawStyle = ToNumber(strLine.substr(0, 1));
var x1=ToNumber(strLine.substr(1, 3));
var y1=ToNumber(strLine.substr(4, 3));
var x2=ToNumber(strLine.substr(7, 3));
var y2=ToNumber(strLine.substr(10, 3));
Line(x1, y1, x2, y2);
var arrTemp=new Array();
for (i=0; i<arrRedo.length-1; i++)
arrTemp[i] = arrRedo[i];
arrRedo = arrTemp;
document.forms[0].redo.disabled = (arrRedo.length == 0);
if (drawStyle == ST_CIRCLE)
{
iLastX=INFINITY;
iLastY=INFINITY;
}
else
{
iLastX = x2;
iLastY = y2;
}
}
function ClearLastLine()
{
var strToClear="";
//alert("points: "+strPoints);
for (j=strPoints.length-2; (j>=0)&&(strPoints.charAt(j) != "|"); j--)
strToClear += strPoints.charAt(j);
strPoints = strPoints.substr(0, strPoints.length-strToClear.length-1);
var strTmp="";
for (k=strToClear.length-1; k>=0; k--)
strTmp += strToClear.charAt(k);
strToClear = strTmp;
var arrTmp=strToClear.split(",");
iPointsCount -= arrTmp.length;
for (i=0; i<arrTmp.length; i++)
document.body.removeChild(document.getElementById(arrTmp[i]));
}
function ClearLastPoint()
{
iLastX=INFINITY;
iLastY=INFINITY;
event.cancelBubble=true;
}
function ToggleShape(a)
{
event.cancelBubble=true;
if (drawStyle == ST_CIRCLE)
{
a.value = "Circle";
drawStyle = ST_LINE;
return ClearLastPoint();
}
if (drawStyle == ST_LINE)
{
a.value = "Line";
drawStyle = ST_CIRCLE;
return ClearLastPoint();
}
return false;
}
次のような HTML が付属しています。
<form>
<input name="clear" id="clear" type=button value="*" onclick="ClearLastPoint();" />
<input name="undo" id="undo" type=button value="Undo" onclick="Undo();" DISABLED />
<input name="redo" id="redo" type=button value="Redo" onclick="Redo();" DISABLED />
<input name="random" id="random" type=button value="Random" onclick="Random();" />
<input name="circle" id="circle" type=button value="Circle" onclick="ToggleShape(this);" />
</form>
このフィドルでオンラインで見ることができます. 単一のピクセル画像を使用しています。ここからダウンロードできます. (右クリックして名前を付けて保存を選択)
もともとは、サーバーへの図面の保存と、従来の ASP を使用した保存済みの図面の読み込みもサポートしていましたが、関係ないので、コードから省略しました。