Javascript 我可以使用 jQuery 画一条线吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11743386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:55:54  来源:igfitidea点击:

Can I draw a line using jQuery?

javascriptjquerycssdrawing

提问by Cris

I have a web app where I would like the user to draw a line in the following way: When he clicks on Point1and he moves the mouse, draw the line from Point1to the current mouse positionand, when clicks to Point2draw the final line from Point1 to Point2.

我有一个网络应用程序,我希望用户通过以下方式画一条线:当他点击Point1并移动鼠标时,从Point1当前鼠标位置绘制线,当点击Point2 时绘制最终从 Point1 到 Point2 的线。

How can I do it using jQuery and/or one of its plugins?

我如何使用 jQuery 和/或其插件之一来做到这一点?

回答by Jonny Burger

Challenge accepted.

已接受的挑战。

I tried to do it with CSS transforms and a bunch of Math in Javascript - after half an hour I have this:

我试图用 CSS 转换和一堆 Javascript 中的数学来做到这一点 - 半小时后我得到了这个:

http://jsfiddle.net/VnDrb/2/

http://jsfiddle.net/VnDrb/2/

Make 2 clicks into the gray square and a line should be drawn. There is still a small bug that draws the line wrong when the angle is > 45 degree. Maybe someone else knows how to fix that. Maybe instead of using Math.asin (arcsinus), use a other trigonometrical function, but I'm really not good at it. I thought I'd post it even there is a small bug, I think it's a good start for you.

在灰色方块中单击 2 次,应绘制一条线。当角度> 45度时,仍然有一个小错误会画错线。也许其他人知道如何解决这个问题。也许不是使用 Math.asin (arcsinus),而是使用其他三角函数,但我真的不擅长。我想即使有一个小错误我也会发布它,我认为这对你来说是一个好的开始。

回答by BaronGrivet

I've tried a number of different approaches this weekend and the solution that worked best for me is from Adam Sanderson: http://monkeyandcrow.com/blog/drawing_lines_with_css3/

本周末我尝试了许多不同的方法,最适合我的解决方案来自 Adam Sanderson:http: //monkeyandcrow.com/blog/drawing_lines_with_css3/

His demo is here: http://monkeyandcrow.com/samples/css_lines/

他的演示在这里:http: //monkeyandcrow.com/samples/css_lines/

The core of it is very simple, which is always good.

它的核心非常简单,这总是好的。

div.line{
  transform-origin: 0 100%;
  height: 3px; /* Line width of 3 */
  background: #000; /* Black fill */
}


function createLine(x1,y1, x2,y2){
  var length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
  var angle  = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
  var transform = 'rotate('+angle+'deg)';

    var line = $('<div>')
      .appendTo('#page')
      .addClass('line')
      .css({
        'position': 'absolute',
        'transform': transform
      })
      .width(length)
      .offset({left: x1, top: y1});

  return line;
}

回答by Rustam

You can not do it with jQuery and classic HTML.

你不能用 jQuery 和经典的 HTML 来做到这一点。

  1. You can do it using SVG (+svgweb for IE8- http://code.google.com/p/svgweb/) SVG can be dynamically created. jQuery + svgweb are working perfectly, you just need to know how to create SVG nodes and you need only jquerify this nodes. After jquerifiing in most cases used only one method attr()

  2. You can do it using Raphael http://raphaeljs.com/(based on SVG and VML)

  3. You can do it using Canvas ( http://flashcanvas.net/for IE8- )

  1. 您可以使用 SVG (+svgweb for IE8- http://code.google.com/p/svgweb/) 来实现 SVG 可以动态创建。jQuery + svgweb 完美运行,您只需要知道如何创建 SVG 节点,并且只需要对这些节点进行 jquerify。大部分情况下jquery之后只用了一种方法attr()

  2. 你可以使用 Raphael http://raphaeljs.com/(基于 SVG 和 VML)

  3. 您可以使用 Canvas ( http://flashcanvas.net/for IE8- )



For SVG programming will be this way:

对于 SVG 编程将是这样的:

  1. Moment of creating first point: you create empty line var Line(also this points coordinates will be x1and y1)

  2. Then you bind on mousemoverepaint of x2, y2properties of Line

  3. On mousedownafter mousemoveyou freeze last line position.

  1. 创建第一个点的时刻:您创建空线var Line(此点坐标将为x1and y1

  2. 然后你绑定mousemove的重绘x2y2线的性质

  3. 在您冻结最后一行位置mousedownmousemove打开。



UPDATE

更新

You can do it with CSS/JS, but main problem is in calculations for IE8-, that has only Matrix filter for transformations.

你可以用 CSS/JS 来做,但主要问题是在 IE8- 的计算中,它只有用于转换的矩阵过滤器。

回答by ClickMatch

Been using a modified version of this for a while now. Works well.

一段时间以来一直在使用这个的修改版本。效果很好。

http://www.ofdream.com/code/css/xline2.php

http://www.ofdream.com/code/css/xline2.php

So on first click, drop and object there as a placeholder div, maybe a little circle, then either keep redrawing a line as they move their mouse, or draw it when they click the second time, using the original placeholder as a guide.

因此,在第一次单击时,将对象放在那里作为占位符 div,可能是一个小圆圈,然后在移动鼠标时继续重画一条线,或者在第二次单击时绘制一条线,使用原始占位符作为指导。

I recently made another helper function for this, because my tool involves moving lines around:

我最近为此做了另一个辅助函数,因为我的工具涉及移动线:

function setLinePos(x1, y1, x2, y2, id) {
    if (x2 < x1) {
        var temp = x1;
        x1 = x2;
        x2 = temp;
        temp = y1;
        y1 = y2;
        y2 = temp;
    }
    var line = $('#line' + id);
    var length = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    line.css('width', length + "px");
    var angle = Math.atan((y2 - y1) / (x2 - x1));
    line.css('top', y1 + 0.5 * length * Math.sin(angle) + "px");
    line.css('left', x1 - 0.5 * length * (1 - Math.cos(angle)) + "px");
    line.css('-moz-transform', "rotate(" + angle + "rad)");
    line.css('-webkit-transform', "rotate(" + angle + "rad)");
    line.css('-o-transform', "rotate(" + angle + "rad)");

 }

That is the jquery version, and in this iteration I have no IE requirement so I ignore it. I could be adapted from the original function pretty easily.

那是 jquery 版本,在这次迭代中我没有 IE 要求,所以我忽略了它。我可以很容易地从原始功能中改编。

回答by Dr.Sai

The class

班上

function getXY(evt, element) {
    var rect = element.getBoundingClientRect();
    var scrollTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
    var elementLeft = rect.left + scrollLeft;
    var elementTop = rect.top + scrollTop;

    x = evt.pageX - elementLeft;
    y = evt.pageY - elementTop;
    return { x: x, y: y };
}
var LineDrawer = {
    LineHTML: `<div style="cursor: pointer;transform-origin:center; position:absolute;width:200px;height:2px; background-color:blue"></div>`,
    isDown: false,
    pStart: {},
    pCurrent :{},
    containerID: "",
    JLine: {},
    angle: 0,
    afterLineCallback: null,
    Init: function (containerID, afterLineCallback) {
        LineDrawer.containerID = containerID;
        LineDrawer.afterLineCallback = afterLineCallback;
        LineDrawer.JLine = $(LineDrawer.LineHTML).appendTo("#" + LineDrawer.containerID);
        LineDrawer.JLine.css("transform-origin", "top left");
        LineDrawer.JLine.hide();
        //LineDrawer.JLine.draggable({ containment: "#" + LineDrawer.containerID });
        $("#" + LineDrawer.containerID).mousedown(LineDrawer.LineDrawer_mousedown);
        $("#" + LineDrawer.containerID).mousemove(LineDrawer.LineDrawer_mousemove);
        $("#" + LineDrawer.containerID).mouseup(LineDrawer.LineDrawer_mouseup);
    },
    LineDrawer_mousedown: function (e) {
        if (e.target === LineDrawer.JLine[0]) return false;
        LineDrawer.isDown = true;
        let p = LineDrawer.pStart = getXY(e, e.target);
        LineDrawer.JLine.css({ "left": p.x, "top": p.y, "width": 1});
        LineDrawer.JLine.show();
    },
    LineDrawer_mousemove: function (e) {
        if (!LineDrawer.isDown) return;
        LineDrawer.pCurrent = getXY(e, document.getElementById("jim"));
        let w = Math.sqrt(((LineDrawer.pStart.x - LineDrawer.pCurrent.x) * (LineDrawer.pStart.x - LineDrawer.pCurrent.x)) + ((LineDrawer.pStart.y - LineDrawer.pCurrent.y) * (LineDrawer.pStart.y - LineDrawer.pCurrent.y)));
        LineDrawer.JLine.css("width", w - 2);
        LineDrawer.angle = Math.atan2((LineDrawer.pStart.y - LineDrawer.pCurrent.y), (LineDrawer.pStart.x - LineDrawer.pCurrent.x)) * (180.0 / Math.PI);
        //the below ensures that angle moves from 0 to -360
        if (LineDrawer.angle < 0) {
            LineDrawer.angle *= -1;
            LineDrawer.angle += 180;
        }
        else LineDrawer.angle = 180 - LineDrawer.angle;
        LineDrawer.angle *= -1;

        LineDrawer.JLine.css("transform", "rotate(" + LineDrawer.angle + "deg");

    },
    LineDrawer_mouseup: function (e) {
        LineDrawer.isDown = false;
        if (LineDrawer.afterLineCallback == null || LineDrawer.afterLineCallback == undefined) return;
        LineDrawer.afterLine(LineDrawer.angle, LineDrawer.pStart, LineDrawer.pCurrent);
    },
};

Usage:

用法:

var ECApp = {
    start_action: function () {
        LineDrawer.Init("jim", ECApp.afterLine);            
    },
    afterLine(angle, pStart, pEnd) {
        //$("#angle").text("angle : " + angle);
        let disp = "angle = " + angle;
        disp += " Start = " + JSON.stringify(pStart) + " End = " + JSON.stringify(pEnd);
        //alert(disp);
        $("#angle").text("angle : " + disp);
    }
}
$(document).ready(ECApp.start_action);

HTML

HTML

<div class="row">
<div class="col">
    <div id="jim" style="position:relative;width:1200px;height:800px;background-color:lightblue;">            
    </div>
</div>