Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Рисование линии на CANVAS (https://javascript.ru/forum/dom-window/40306-risovanie-linii-na-canvas.html)

essere 31.07.2013 09:49

Рисование линии на CANVAS
 
Всем добра!
Господа, у меня есть опыт работы с JS/Jquery, но никогда не работал с CANVAS'ом.
Есть задачка:
Есть холст, на нем пользователь ставит первую точку, вторую точку. И, между ними рисуется линия.
Потом пользователь рисует вторую линию, точно так же.
Задача: найти середины этих линий и провести от них перпендикуляры (эта линия, которая лежит под углом 90 градусов).
Синьоры, я хочу разобраться, может быть есть библиотечка какая-нибудь по работе с канвасом, ну и вообще, как логически решить задачу. Список методов по работе с этим объектом то найти не проблема, а вот как стартануть.
Спасибо

essere 31.07.2013 11:20

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265190)
А в чем проблема? Нарисовать линию или вычислить перпендикуляр?
Для таких простых вещей библиотеки не нужны.)

Ну например, для того чтобы поставить на канве точки.
Полагаю как то надо сначала получить координаты "клика", потом координаты второго клика.
Нашел функцию получения координат:
function cnvs_getCoordinates(e) {
            x=e.clientX;
            y=e.clientY;
            document.getElementById("xycoordinates").innerHTML="Coordinates: (" + x + "," + y + ")";
}

Почему то не работает в секции $(document).ready(function() {...

essere 31.07.2013 11:23

Во, даже вот так:
function cnvs_getCoordinates(e) {
            $("#xycoordinates").text( e.clientX + "," + e.clientY );
}

essere 31.07.2013 11:35

Потом, логично создать функцию рисования самой линии. Объявив ее вне секции $(document).ready(function() {...
А уже в $(document).ready(function() {... мы ее вызываем.
function drowLine(x_first, y_first, x_second, y_second) {
            var canvas = document.getElementById("myCanvas");  
            var ctx = canvas.getContext("2d");
            ctx.moveTo( x_first, y_first );
            ctx.lineTo( x_second, y_second );
            ctx.stroke();
        }

essere 31.07.2013 11:44

Но ведь промежуточный итог тоже же где то хранить надо т.е. координаты точка1 и координаты точка2, а потооом уже только вызывать функцию рисования.

essere 31.07.2013 12:25

Спасибо, изучу.
Но дошел до
var coords = [];

        function getCoords(e)
        {
            coords.push(e.clientX, e.clientY);

            if (coords.length === 4) {
                //alert(coords[0] +','+ coords[1] +','+ coords[2] +','+ coords[3]);

                drowLine(coords[0], coords[1], coords[2], coords[3]);

                coords = [];
            }
        }

Вот так хранить координаты

essere 31.07.2013 14:24

Вобщем вот такая красота получилась:
<body>  
    <canvas onclick="getCoords(event)" style="border: 1px solid #c6c6c6" id="myCanvas" width="500" height="500">
          <!-- Insert fallback content here -->  
    </canvas>  
    <script>  

    var coords = [];
    var perps = [];

    var ctx = document.getElementById("myCanvas").getContext("2d");

        function getCoords(e)
        {
            //alert(e.clientX + " на " + e.clientY);

            drawCircle(e.clientX, e.clientY, 3);
                
            coords.push(e.clientX, e.clientY);

            if (coords.length === 4) {
                x1 = coords[0]; y1 = coords[2];
                x2 = coords[1]; y2 = coords[3];

                var perpX = (x1 + y1)/2;
                var perpY = (x2 + y2)/2;

                drawCircle(perpX, perpY, 3);

                //drawLine(perpX, perpY, perpX+200, perpY+200);
                drawLine(coords[0], coords[1], coords[2], coords[3]);
                coords = [];

            }
        }


    function drawLine(x_first, y_first, x_second, y_second) 
    {
        ctx.beginPath();   
        ctx.moveTo( x_first, y_first );
        ctx.lineTo( x_second, y_second );
        ctx.lineWidth = 2; 
        ctx.stroke();
    }

    function drawCircle(x, y, radius) 
    {
        ctx.beginPath();  
        ctx.arc(x, y, radius, 0, Math.PI*2, false);  
        ctx.closePath();  
        ctx.fill();  
    }

    $(document).ready(function() 
    {  
        //drawLine(100, 100, 250, 300);
         //var canvas = document.getElementById("myCanvas");  
         //var ctx = canvas.getContext("2d");  
         //...
    });  

   </script>  
   </body>

Вот только не могу понять, как перпендикуляр отвести, старт то известно откуда "вести" его, а вот куда ...

essere 31.07.2013 15:50

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265274)
Комментарии в коде для кого написаны? :cray:

// половинный вектор перпендикуляра
var perpHalfDX = -dy / lineLen * perpLen / 2;
var perpHalfDY = +dx / lineLen * perpLen / 2;

...


// перпендикуляр

ctx.beginPath();
ctx.moveTo( midX - perpHalfDX, midY - perpHalfDY );
ctx.lineTo( midX + perpHalfDX, midY + perpHalfDY );
ctx.stroke();

Да это я пробовал:
var coords = [];
    var perps = [];

    var ctx = document.getElementById("myCanvas").getContext("2d");

        function getCoords(e)
        {
            //alert(e.clientX + " на " + e.clientY);

            drawCircle(e.clientX, e.clientY, 3);
                
            coords.push(e.clientX, e.clientY);

            if (coords.length === 4) {
                x1 = coords[0]; y1 = coords[2];
                x2 = coords[1]; y2 = coords[3];

                var dx = x2 - x1;
                var dy = y2 - y1;
                var lineLen = Math.sqrt( dx * dx + dy * dy );

                var perpHalfDX = -dy / lineLen * perpLen / 2;
                var perpHalfDY = +dx / lineLen * perpLen / 2;

        
                var perpX = (x1 + y1)/2;
                var perpY = (x2 + y2)/2;
                
                ctx.beginPath();
                ctx.moveTo( perpX - perpHalfDX, perpY - perpHalfDY );
                ctx.lineTo( perpX + perpHalfDX, perpY + perpHalfDY );
                ctx.stroke();

                drawCircle(perpX, perpY, 3);

                //drawLine(perpX, perpY, perpX+200, perpY+200);
                drawLine(coords[0], coords[1], coords[2], coords[3]);
                coords = [];

            }
        }


    function drawLine(x_first, y_first, x_second, y_second) 
    {
        ctx.beginPath();   
        ctx.moveTo( x_first, y_first );
        ctx.lineTo( x_second, y_second );
        ctx.lineWidth = 2; 
        ctx.stroke();
    }

    function drawCircle(x, y, radius) 
    {
        ctx.beginPath();  
        ctx.arc(x, y, radius, 0, Math.PI*2, false);  
        ctx.closePath();  
        ctx.fill();  
    }

    $(document).ready(function() 
    {  
        //drawLine(100, 100, 250, 300);
         //var canvas = document.getElementById("myCanvas");  
         //var ctx = canvas.getContext("2d");  
         //...
    });

Только не работает оно.
Математика чертова ;[

essere 31.07.2013 16:22

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265280)
почему perpLen не определен?

и почему
var perpX = (x1 + y1)/2;
var perpY = (x2 + y2)/2;

если нужно
var perpX = (x1 + x2)/2;
var perpY = (y1 + y2)/2;

???

coords.push(e.clientX, e.clientY);

x1 = coords[0]; y1 = coords[2];
x2 = coords[1]; y2 = coords[3];

тут вообще иксы и игреки перепутаны...

блин, ну нельзя же быть настолько невнимательным)

Почему перепутаны то) Это я сам писал.

essere 31.07.2013 16:26

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265284)
А мой код, который я писал в соответствии с тем что x - это всегда икс, а y - всегда игрек, должен заработать на неправильном сопоставлении переменных автоматически?

Просто из курса школьной геометрии помнится х1 у1, х2 у2 и т.д.

essere 31.07.2013 16:31

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265284)
тогда еще раз: почему perpLen не определен?

Да это вечер, давно он уже определен))

essere 31.07.2013 16:59

Честно говоря совсем запутался, что есть х что у, вобщем у себя менял местами, заработало. Но правда математика так и осталась загадкой.

essere 31.07.2013 17:02

Да, все правильно, это меня геометрия сбила с толку, все правильно х и там и там.
Осталось смещение убрать ;]

essere 31.07.2013 17:13

Дзен-трансгуманист,
Спасибо Вам ;]
Вот получилось вот такая красота:
var coords = [];
    var perps = [];

    var ctx = document.getElementById("myCanvas").getContext("2d");

        function getCoords(e)
        {

            drawCircle(e.clientX, e.clientY, 3);
                
            coords.push(e.clientX, e.clientY);

            if (coords.length === 4) {

                x1 = coords[0]; x2 = coords[2];
                y1 = coords[1]; y2 = coords[3];

                var dx = x2 - x1;
                var dy = y2 - y1;
                //var lineLen = Math.sqrt( dx * dx + dy * dy );

                var perpHalfDX = -dy / 150 * 100;
                var perpHalfDY = +dx / 150 * 100;

        
                var perpX = (x1 + x2)/2;
                var perpY = (y1 + y2)/2;

                drawLine(perpX, perpY, perpX + perpHalfDX, perpY + perpHalfDY);

                drawCircle(perpX, perpY, 3);

                //drawLine(perpX, perpY, perpX+200, perpY+200);
                drawLine(coords[0], coords[1], coords[2], coords[3]);
                coords = [];

            }
        }


    function drawLine(x_first, y_first, x_second, y_second) 
    {
        ctx.beginPath();   
        ctx.moveTo( x_first, y_first );
        ctx.lineTo( x_second, y_second );
        ctx.lineWidth = 2; 
        ctx.stroke();
    }

    function drawCircle(x, y, radius) 
    {
        ctx.beginPath();  
        ctx.arc(x, y, radius, 0, Math.PI*2, false);  
        ctx.closePath();  
        ctx.fill();  
    }

essere 31.07.2013 17:18

А можно самый страшный вопрос? Вот убрал смещение перпендикуляра, теперь все классно. Нарисовал линию и теперь от ее центра пошел длинный перпендикуляр.
Если нарисовать две линии, так, чтобы перпендикуляры пересеклись, как можно найти его угол? Логически.

essere 31.07.2013 18:01

Вложений: 1
Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265306)
сумма углов четырехугольника 360 градусов
без двух перпендикуляров остается 180
угол между линиями = 180 - угол между перпендикулярами (и наоборот)

Т.е. Я правильно Вас понял, что в расчете участвуют абсолютно все точки?
Вложение 1881

essere 31.07.2013 18:17

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 265317)
Нет, только векторы самих линий.

мне лень объяснять, прошу в гугл: "угол между векторами", "векторная алгебра" и прочая-прочая :)

Ок спасибо, формулу найду. Посчитаю.
Кстати, а сами точки можно как то двигать? Т.е. я поставил линию, могу ли я как то одну из точек передвинуть, а не обнулять все. Как мне ее подхватить, понятно, что тут будет onmousemove событие, но как мне за существующую точку захватиться?


Часовой пояс GMT +3, время: 23:09.