如何根据鼠标移动绘制线条

时间:2012-05-02 14:38:19

标签: javascript

我正在寻找一种在鼠标开始结束时划一条线的方法。例如,我有DIV,我已经以圆形方式移动鼠标。但我希望在鼠标移动的路径中绘制一条线。

我不是在寻找任何HTML5解决方案。我希望它甚至可以在所有现代浏览器中使用。

请帮我解决这个问题。

2 个答案:

答案 0 :(得分:3)

如果您希望它适用于所有现代浏览器,请使用HTML5

如果您想支持旧浏览器,那么您可以使用http://raphaeljs.com/ JS库

Raphael使用SVG(如果可用),否则使用VML。基本上除IE8及以下版本的每个浏览器都将使用SVG。

答案 1 :(得分:1)

我在8年前写过一些东西,6年前修改过它并现在检查它 - 仍在工作。它是通过点击屏幕上的两个点绘制线条,但可以改为鼠标移动而不需要调整。

它采用纯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>

您可以在this fiddle在线查看。 它使用单个像素图像,您可以下载它here。 (右键单击并选择另存为)

最初它还支持将绘图保存到服务器并使用经典ASP加载已保存的图形,但我认为它与您无关,所以我在代码中省略了它。