Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.03.2018, 21:24
Интересующийся
Отправить личное сообщение для ar4ipers Посмотреть профиль Найти все сообщения от ar4ipers
 
Регистрация: 26.03.2018
Сообщений: 25

Drag and Drop, пересечение полигонов
Здравствуйте, учу js, на данный момент изучаю работу с DOM. Реализовываю Drag and Drop с полигонами, при пересечении полигонов, необходимо чтобы пересекаемые полигоны становились красными, не могу понять в почему работает только с с первым объектом из массива, может подскажет кто??
window.onload = function () {
    var canvas = document.getElementById('lienzo');
    if (canvas && canvas.getContext) {
        var ctx = canvas.getContext('2d');
        if (ctx) {

            width = canvas.width = window.innerWidth - 5;
            height = canvas.height = window.innerHeight - 5;
            var isDragging = false;
            var delta = new Object();
            function drawPoligon(poligon) {
                ctx.beginPath();
                ctx.moveTo(poligon.points[0].x, poligon.points[0].y);
                for (var i = 1; i < poligon.points.length; i++) {
                    ctx.lineTo(poligon.points[i].x, poligon.points[i].y);
                }
                ctx.closePath();
                ctx.fill();
            }
            function updatePoligon(star) {
                for (var i = 0; i < star.points.length; i++) {
                    star.points[i].x = star.x + star.offset[i].x;
                    star.points[i].y = star.y + star.offset[i].y;
                }
            }
            function updatePoligons() {
                for (var i = 0; i < list.length; i++) {
                    updatePoligon(list[i]);
                }
            }
            function drawPoligons() {
                for (var i = 0; i < list.length; i++) {
                    drawPoligon(list[i]);
                }
            }

            var list = [
                {
                    'x': 50,
                    'y': 100,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                    ],
                    'offset': [
                        { 'x': 50, 'y': 0 },
                        { 'x': 5, 'y': -48 },
                        { 'x': -40, 'y': 0 },
                        { 'x': 5, 'y': 48 },
                    ],
                    'bool': false
                },
                {
                    'x': 50,
                    'y': 200,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                    ],
                    'offset': [
                        { 'x': 25, 'y': -48 },
                        { 'x': -15, 'y': -48 },
                        { 'x': -40, 'y': 0 },
                        { 'x': -15, 'y': 48 }, 
                        { 'x': 25, 'y': 48 },
                        { 'x': 50, 'y': 0 },
                    ],
                    'bool': false
                },
                {
                    'x': 50,
                    'y': 300,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 }
                    ],
                    'offset': [
                        { 'x': 50, 'y': 0 },
                        { 'x': 20, 'y': 14 },
                        { 'x': 15, 'y': 48 },
                        { 'x': -8, 'y': 24 },
                        { 'x': -40, 'y': 29 },
                        { 'x': -25, 'y': 0 },
                        { 'x': -40, 'y': -29 },
                        { 'x': -8, 'y': -24 },
                        { 'x': 15, 'y': -48 },
                        { 'x': 20, 'y': -14 }
                    ],
                    'bool': false
                }
            ];
            updatePoligons()
            drawPoligons();

            function oMousePos(canvas, evt) {
                var rect = canvas.getBoundingClientRect();
                return {
                    x: parseInt(evt.clientX - rect.left),
                    y: parseInt(evt.clientY - rect.top)
                };
            }
            function checkStarCollision(starA, starB) {
                for (var i = 0; i < starA.points.length; i++) {
                    var p0 = starA.points[i],
                        p1 = starA.points[(i + 1) % starA.points.length];

                    for (var j = 0; j < starB.points.length; j++) {
                        var p2 = starB.points[j],
                            p3 = starB.points[(j + 1) % starB.points.length];

                        if (segmentIntersect(p0, p1, p2, p3)) {
                            return true;
                        }
                    }
                }
                return false;
            }

            function segmentIntersect(p0, p1, p2, p3) {
                var A1 = p1.y - p0.y,
                    B1 = p0.x - p1.x,
                    C1 = A1 * p0.x + B1 * p0.y,
                    A2 = p3.y - p2.y,
                    B2 = p2.x - p3.x,
                    C2 = A2 * p2.x + B2 * p2.y,
                    denominator = A1 * B2 - A2 * B1;

                if (denominator == 0) {
                    return null;
                }

                var intersectX = (B2 * C1 - B1 * C2) / denominator,
                    intersectY = (A1 * C2 - A2 * C1) / denominator,
                    rx0 = (intersectX - p0.x) / (p1.x - p0.x),
                    ry0 = (intersectY - p0.y) / (p1.y - p0.y),
                    rx1 = (intersectX - p2.x) / (p3.x - p2.x),
                    ry1 = (intersectY - p2.y) / (p3.y - p2.y);

                if (((rx0 >= 0 && rx0 <= 1) || (ry0 >= 0 && ry0 <= 1)) &&
                    ((rx1 >= 0 && rx1 <= 1) || (ry1 >= 0 && ry1 <= 1))) {
                    return {
                        x: intersectX,
                        y: intersectY
                    };
                }
                else {
                    return null;
                }
            }
            // mousedown ***************************
            canvas.addEventListener('mousedown', function (evt) {
                isDragging = true;
                var mousePos = oMousePos(canvas, evt);
                for (var i = 0; i < list.length; i++) {
                    drawPoligon(list[i]);
                    if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
                        list[i].bool = true;
                        delta.x = list[i].x - mousePos.x;
                        delta.y = list[i].y - mousePos.y;
                        break;
                    } else {
                        list[i].bool = false;
                    }
                }
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawPoligons();
            }, false);
            // mousemove ***************************
            canvas.addEventListener('mousemove', function (evt) {
                if (isDragging) {

                    var mousePos = oMousePos(canvas, evt),
                        selectPoligon;
                    for (var i = 0; i < list.length; i++) {
                        if (list[i].bool) {
                            ctx.clearRect(0, 0, width, height);
                            list[i].x = mousePos.x + delta.x;
                            list[i].y = mousePos.y + delta.y;
                            selectPoligon = list[i];
                        }
                        updatePoligon(list[i]);
                        if (checkStarCollision(selectPoligon, list[i])) {
                            ctx.fillStyle = "red";
                        }
                        else {
                            ctx.fillStyle = "black";
                        }
                        drawPoligon(list[i]);
                    }
                }
            }, false);
            // mouseup ***************************
            canvas.addEventListener('mouseup', function (evt) {
                isDragging = false;
                for (var i = 0; i < list.length; i++) { list[i].bool = false }
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawPoligons();
            }, false);
            // mouseout ***************************
            canvas.addEventListener('mouseout', function (evt) {
                isDragging = false;
                for (var i = 0; i < list.length; i++) { list[i].bool = false }
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawPoligons();
            }, false);
        }
    }
}

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>Canvas Figures</title>
	<style>
		html,
		body {
			width: 100%;
			margin: 0;
			background-color: #78909C;			
		}

		#lienzo {
			width: 100%;
			background-color: #37474F;
			
		}
	</style>
</head>

<body>
	<canvas id="lienzo"></canvas>
	<script src="Javascript/app.js"></script>
</body>

</html>
Ответить с цитированием
  #2 (permalink)  
Старый 26.03.2018, 23:05
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

ar4ipers,
со строки 190
сначала определить selectPoligon и только потом им оперировать, вынести строки 192 - 197 в отдельный цикл, перед строкой 191.
Ответить с цитированием
  #3 (permalink)  
Старый 26.03.2018, 23:21
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

ar4ipers,
строку 169 перенести на 174
Ответить с цитированием
  #4 (permalink)  
Старый 27.03.2018, 14:50
Интересующийся
Отправить личное сообщение для ar4ipers Посмотреть профиль Найти все сообщения от ar4ipers
 
Регистрация: 26.03.2018
Сообщений: 25

Спасибо, разобрался с этим, был невнимателен. Далее пытаюсь сделать чтобы объект обновлял свое состояние после drop'а. Если после drop'а два
объекта пересекаются они должны поменять цвет заливки фигуры. Изменил метод mousemove. Получил вот такое
canvas.addEventListener('mousemove', function (evt) {
                if (isDragging) {
                    var mousePos = oMousePos(canvas, evt);
                    for (var i = 0; i < list.length; i++) {
                        if (list[i].bool) {
                            updatePoligon(list[i]);
                            ctx.clearRect(0, 0, width, height);
                            var X = mousePos.x + delta.x, Y = mousePos.y + delta.y
                            list[i].x = X;
                            list[i].y = Y;
                            selectPoligon = list[i];
                            break;
                        }
                    }
                    drawPoligons();
                }
            }, false);

и изменил метод mouseup, получилось вот такое
canvas.addEventListener('mouseup', function (evt) {
                isDragging = false;
                for (var i = 0; i < list.length; i++) {
                    list[i].bool = false
                }
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                for (var i = 0; i < list.length; i++) {
                    if (checkStarCollision(selectPoligon, list[i])) {
                        ctx.fillStyle = "red";
                    }
                    else{
                        ctx.fillStyle = "black";
                    }
                    drawPoligon(list[i]);
                }
            }, false);

Но цвета прыгают, т.е. после дропа если два полигона пересекаются, они красными становятся, но так же если не пересекаются, то полигон который двигал, становится красным, а если двигаю 3-ю фигуру, то во время mousemove, становятся красными и все остальные, моет поскажет кто где косяк?
Ответить с цитированием
  #5 (permalink)  
Старый 27.03.2018, 14:55
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

пересечение полигонов
ar4ipers,
код нуждается в оптимизации ...
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Canvas Figures</title>
  <style>
    html,
    body {
      width: 100%;
      margin: 0;
      background-color: #78909C;
    }

    #lienzo {
      width: 100%;
      background-color: #37474F;

    }
  </style>
</head>

<body>
  <canvas id="lienzo"></canvas>
  <script>window.onload = function () {
    var canvas = document.getElementById('lienzo');
    if (canvas && canvas.getContext) {
        var ctx = canvas.getContext('2d');
        if (ctx) {

            width = canvas.width = window.innerWidth - 5;
            height = canvas.height = window.innerHeight - 5;
            var isDragging = false;
            var delta = new Object();
            function drawPoligon(poligon) {
                ctx.beginPath();
                ctx.moveTo(poligon.points[0].x, poligon.points[0].y);
                for (var i = 1; i < poligon.points.length; i++) {
                    ctx.lineTo(poligon.points[i].x, poligon.points[i].y);
                }
                ctx.closePath();
                ctx.fill();
            }
            function updatePoligon(star) {
                for (var i = 0; i < star.points.length; i++) {
                    star.points[i].x = star.x + star.offset[i].x;
                    star.points[i].y = star.y + star.offset[i].y;
                }
            }
            function updatePoligons() {
                for (var i = 0; i < list.length; i++) {
                    updatePoligon(list[i]);
                }
            }
            function drawPoligons() {
                for (var i = 0; i < list.length; i++) {
                    drawPoligon(list[i]);
                }
            }

            var list = [
                {
                    'x': 50,
                    'y': 100,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                    ],
                    'offset': [
                        { 'x': 50, 'y': 0 },
                        { 'x': 5, 'y': -48 },
                        { 'x': -40, 'y': 0 },
                        { 'x': 5, 'y': 48 },
                    ],
                    'bool': false
                },
                {
                    'x': 50,
                    'y': 200,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                    ],
                    'offset': [
                        { 'x': 25, 'y': -48 },
                        { 'x': -15, 'y': -48 },
                        { 'x': -40, 'y': 0 },
                        { 'x': -15, 'y': 48 },
                        { 'x': 25, 'y': 48 },
                        { 'x': 50, 'y': 0 },
                    ],
                    'bool': false
                },
                {
                    'x': 50,
                    'y': 300,
                    'color': '#3F51B5',
                    'points': [
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 },
                        { 'x': 0, 'y': 0 }
                    ],
                    'offset': [
                        { 'x': 50, 'y': 0 },
                        { 'x': 20, 'y': 14 },
                        { 'x': 15, 'y': 48 },
                        { 'x': -8, 'y': 24 },
                        { 'x': -40, 'y': 29 },
                        { 'x': -25, 'y': 0 },
                        { 'x': -40, 'y': -29 },
                        { 'x': -8, 'y': -24 },
                        { 'x': 15, 'y': -48 },
                        { 'x': 20, 'y': -14 }
                    ],
                    'bool': false
                }
            ];
            updatePoligons()
            drawPoligons();

            function oMousePos(canvas, evt) {
                var rect = canvas.getBoundingClientRect();
                return {
                    x: parseInt(evt.clientX - rect.left),
                    y: parseInt(evt.clientY - rect.top)
                };
            }
            function checkStarCollision(starA, starB) {
                for (var i = 0; i < starA.points.length; i++) {
                    var p0 = starA.points[i],
                        p1 = starA.points[(i + 1) % starA.points.length];

                    for (var j = 0; j < starB.points.length; j++) {
                        var p2 = starB.points[j],
                            p3 = starB.points[(j + 1) % starB.points.length];

                        if (segmentIntersect(p0, p1, p2, p3)) {
                            return true;
                        }
                    }
                }
                return false;
            }

            function segmentIntersect(p0, p1, p2, p3) {
                var A1 = p1.y - p0.y,
                    B1 = p0.x - p1.x,
                    C1 = A1 * p0.x + B1 * p0.y,
                    A2 = p3.y - p2.y,
                    B2 = p2.x - p3.x,
                    C2 = A2 * p2.x + B2 * p2.y,
                    denominator = A1 * B2 - A2 * B1;

                if (denominator == 0) {
                    return null;
                }

                var intersectX = (B2 * C1 - B1 * C2) / denominator,
                    intersectY = (A1 * C2 - A2 * C1) / denominator,
                    rx0 = (intersectX - p0.x) / (p1.x - p0.x),
                    ry0 = (intersectY - p0.y) / (p1.y - p0.y),
                    rx1 = (intersectX - p2.x) / (p3.x - p2.x),
                    ry1 = (intersectY - p2.y) / (p3.y - p2.y);

                if (((rx0 >= 0 && rx0 <= 1) || (ry0 >= 0 && ry0 <= 1)) &&
                    ((rx1 >= 0 && rx1 <= 1) || (ry1 >= 0 && ry1 <= 1))) {
                    return {
                        x: intersectX,
                        y: intersectY
                    };
                }
                else {
                    return null;
                }
            }
            // mousedown ***************************
            canvas.addEventListener('mousedown', function (evt) {

                var mousePos = oMousePos(canvas, evt);
                for (var i = 0; i < list.length; i++) {
                        drawPoligon(list[i]);
                    if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
                        isDragging = true;
                        list[i].bool = true;
                        delta.x = list[i].x - mousePos.x;
                        delta.y = list[i].y - mousePos.y;
                        break;
                    } else {
                        list[i].bool = false;
                    }

                }

                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawPoligons();
            }, false);
            // mousemove ***************************
            canvas.addEventListener('mousemove', function (evt) {
                if (isDragging) {

                    var mousePos = oMousePos(canvas, evt),
                        selectPoligon;
                    for (var i = 0; i < list.length; i++) {
                        if (list[i].bool) {
                            ctx.clearRect(0, 0, width, height);
                            list[i].x = mousePos.x + delta.x;
                            list[i].y = mousePos.y + delta.y;
                            updatePoligon(list[i]);
                            selectPoligon = list[i];
                        }
                    }
                    for (var i = 0; i < list.length; i++) {


                        if (checkStarCollision(selectPoligon, list[i])) {
                            ctx.fillStyle = "red";
                        }
                        else {
                            ctx.fillStyle = "black";
                        }
                        drawPoligon(list[i]);
                    }
                }
            }, false);
            // mouseup ***************************
            canvas.addEventListener('mouseup', function (evt) {
                isDragging = false;ctx.fillStyle = "black";
                for (var i = 0; i < list.length; i++) { list[i].bool = false }
                ctx.clearRect(0, 0, canvas.width, canvas.height);

                drawPoligons();
            }, false);
            // mouseout ***************************
            canvas.addEventListener('mouseout', function (evt) {
                isDragging = false;
                for (var i = 0; i < list.length; i++) { list[i].bool = false }
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                drawPoligons();
            }, false);
        }
    }
}

</script>
</body>

</html>

Последний раз редактировалось рони, 12.05.2019 в 14:23.
Ответить с цитированием
  #6 (permalink)  
Старый 27.03.2018, 15:18
Интересующийся
Отправить личное сообщение для ar4ipers Посмотреть профиль Найти все сообщения от ar4ipers
 
Регистрация: 26.03.2018
Сообщений: 25

Спасибо, я так понимаю нужно drawPoligon переделать
Ответить с цитированием
  #7 (permalink)  
Старый 27.03.2018, 15:23
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

Сообщение от ar4ipers
я так понимаю нужно drawPoligon переделать
сейчас что - то не так?
Ответить с цитированием
  #8 (permalink)  
Старый 27.03.2018, 15:33
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

ar4ipers,
мысли вслух ...
if (checkStarCollision(selectPoligon, list[i])) {
                            ctx.fillStyle = "red";
                        }
                        else {
                            ctx.fillStyle = "black";
                        }


if (checkStarCollision(selectPoligon, list[i])) {
                            list[i].color = "red";
                        }
                        else {
                            list[i].color = "black";
                        }


function drawPoligon(poligon) {
                ctx.beginPath();
*!*
ctx.fillStyle = poligon.color ? poligon.color : curentColor;
*/!*
                ctx.moveTo(poligon.points[0].x, poligon.points[0].y);
                for (var i = 1; i < poligon.points.length; i++) {
                    ctx.lineTo(poligon.points[i].x, poligon.points[i].y);
                }
                ctx.closePath();
                ctx.fill();
            }


if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
                        isDragging = true;
                        list[i].bool = true;
*!*
selectPoligon = list[i];
*/!*
                        delta.x = list[i].x - mousePos.x;
                        delta.y = list[i].y - mousePos.y;
                        break;
                    }
Ответить с цитированием
  #9 (permalink)  
Старый 27.03.2018, 15:49
Интересующийся
Отправить личное сообщение для ar4ipers Посмотреть профиль Найти все сообщения от ar4ipers
 
Регистрация: 26.03.2018
Сообщений: 25

Спасибо, тот вариант который вы подсказали вчера, я разобрался, понял в чем была ошибка, а теперь подумал как сделать чтобы цвета менялись после drop'a именно, спасибо за решение, а не подскажете как вообще мне лучше оптимизировать код, может вообще лучше создать класс Poligon и непосредственно работать уже с ним или же данная реализация тоже вполне себе корректна?
Ответить с цитированием
  #10 (permalink)  
Старый 27.03.2018, 16:42
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,124

Сообщение от ar4ipers
лучше создать класс Poligon
как вам удобнее, на сколько позволяет опыт абстрагировать ...
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Криво работает drag & drop Dark Souls jQuery 6 06.03.2017 22:32
ищу Drag & drop плагин для построения плана помещения Den Brown Элементы интерфейса 0 31.07.2015 19:23
Помощь с Drag & Drop Zuko jQuery 0 22.03.2015 09:18
drag & drop , html 5 cyber Events/DOM/Window 1 30.06.2012 15:16
Drag & Drop с несколькими элементами Katz Общие вопросы Javascript 1 29.07.2011 13:01