Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 15.06.2018, 14:02
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

Помогите понять Canvas
Не могу понять как работать с канвасом.
Вот мой пример (canvas и блок с размерами):
<style>.skat-size{display:inline-block;margin:15px 10px;padding:0 10px 10px;border:solid 1px #ccc;}</style>

<canvas id="valma" width="420" height="220">Конверт</canvas>

<div class="row plos" data-area="valma">
    <div class="skat-size">
        <h4>Трапеция</h4>
        <div>Карниз:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Конёк:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Высота:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
    </div>
    <div class="skat-size">
        <h4>Треугольный скат</h4>
        <div>Длина карниза:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Высота ската:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
    </div>
</div>


<script>
var canvasValma = document.querySelector('canvas#valma');

function canvasRoof() {
    let valm_sk1 = '#bbb',
        valm_sk2 = '#ccc',
        valm_sk3 = '#ddd',
        valm_sk4 = '#ccc';
    
    let valma = canvasValma.getContext('2d');

    if (canvasValma && canvasValma.getContext) {
        valma.fillStyle = '#fff';
        valma.fillRect(0, 0, 420, 220);
        
        valma.beginPath();   // 1 сторона
        valma.moveTo(0, 0);
        valma.lineTo(400, 0);
        valma.lineTo(300, 100);
        valma.lineTo(100, 100);
        valma.fillStyle = valm_sk1;
        valma.fill();
        
        valma.beginPath();   // 2 сторона
        valma.moveTo(400, 0);
        valma.lineTo(300, 100);
        valma.lineTo(400, 200);
        valma.fillStyle = valm_sk2;
        valma.fill();

        valma.beginPath();   // 3 сторона
        valma.moveTo(0, 200);
        valma.lineTo(100, 100);
        valma.lineTo(300, 100);
        valma.lineTo(400, 200);
        valma.fillStyle = valm_sk3;
        valma.fill();

        valma.beginPath();   // 4 сторона
        valma.moveTo(0, 0);
        valma.lineTo(100, 100);
        valma.lineTo(0, 200);
        valma.fillStyle = valm_sk4;
        valma.fill();
    }
}


canvasRoof();

function razmStrel(color, v, lw) {   // Принимает: color - цвет, v - координаты (массив), lw - толщина линии
    let strelka = canvasValma.getContext('2d');

    if (canvasValma && canvasValma.getContext) {
        // Размерные стрелки
        strelka.strokeStyle = color;
        strelka.lineWidth = lw;
        strelka.beginPath();
        strelka.moveTo(v[0], v[1]);
        strelka.lineTo(v[2], v[3]);
        strelka.stroke();

        strelka.beginPath();
        strelka.lineWidth = 1;
        strelka.moveTo(v[4], v[5]);
        strelka.lineTo(v[6], v[7]);
        strelka.lineTo(v[8], v[9]);
        strelka.stroke();

        strelka.beginPath();
        strelka.lineWidth = 1;
        strelka.moveTo(v[10], v[11]);
        strelka.lineTo(v[12], v[13]);
        strelka.lineTo(v[14], v[15]);
        strelka.stroke();
    }
}

var inp = document.querySelectorAll('input');
for (let i = 0; i < inp.length; i++) {
    inp[i].addEventListener('focus', function() {
        let color = 'green',
            v,
            lw = 2;
        switch (i) {    //Для вальмы
            case 0: v = [0,210, 400,210, 15,207, 0,210, 15,213, 385,207, 400,210, 385,213]; break;
            case 1: v = [100,115, 300,115, 115,112, 100,115, 115,118, 285,112, 300,115, 285,118]; break;
            case 2: v = [120,100, 120,200, 117,115, 120,100, 123,115, 117,185, 120,200, 123,185]; break;
            case 3: v = [410,0, 410,200, 407,15, 410,0, 413,15, 407,185, 410,200, 413,185]; break;
            case 4: v = [300,100, 400,100, 315,97, 300,100, 315,103, 385,97, 400,100, 385,103]; break;
        }

        razmStrel(color, v, lw);
    })

    inp[i].addEventListener('blur', () => canvasRoof());
    
}
</script>

Я нарисовал фигуру, но не знаю как мне реализовать интерактивность. Нужно сигменты из канваса на отдельные части разделять или как это делается?
Например, чтобы при наведении курсора на блок с размерами (инпутами), на канвасе менял цвет соответствующий фрагмент.
А при установке фокуса в инпуте, появлялась размерная стрелка в нужном месте, при выходе из фокуса стрелка убиралась.

Последний раз редактировалось MC-XOBAHCK, 15.06.2018 в 19:10. Причина: Изменил код на новую версию
Ответить с цитированием
  #2 (permalink)  
Старый 15.06.2018, 18:00
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

Думал-думал, попробовал несколько идей и смог функцию надумать добавляющую стрелки (код в топике исправил).

Только при фокусе в инпуте стрелки добавляются, а как их убрать когда фокус снимается???
Ответить с цитированием
  #3 (permalink)  
Старый 15.06.2018, 18:16
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 27.11.2015
Сообщений: 2,899

Сообщение от MC-XOBAHCK
как их убрать когда фокус снимается
Перерисовывать canvas без них
Ответить с цитированием
  #4 (permalink)  
Старый 15.06.2018, 18:57
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,135

MC-XOBAHCK,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">

</head>

<body>
<div id="slider"></div>
<style>.skat-size{display:inline-block;margin:15px 10px;padding:0 10px 10px;border:solid 1px #ccc;}</style>

<canvas id="valma-test2" width="420" height="220">Конверт</canvas>

<div class="row plos" data-area="valma">
    <div class="skat-size">
        <h4>Трапеция</h4>
        <div>Карниз:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Конёк:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Высота:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
    </div>
    <div class="skat-size">
        <h4>Треугольный скат</h4>
        <div>Длина карниза:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
        <div>Высота ската:</div>
        <div>
            <input class="valma" type="text" /><span class="unit"> м</span>
        </div>
    </div>
</div>


<script>
let valm_sk1 = '#bbb',
    valm_sk2 = '#ccc',
    valm_sk3 = '#ddd',
    valm_sk4 = '#ccc';
var canvasValma2 = document.querySelector('#valma-test2');
function draw()
{

    let valma = canvasValma2.getContext('2d');
    if (valma) {
        valma.clearRect(0, 0, 420, 220);
        valma.beginPath();   // 1 сторона
        valma.moveTo(0, 0);
        valma.lineTo(400, 0);
        valma.lineTo(300, 100);
        valma.lineTo(100, 100);
        valma.fillStyle = valm_sk1;
        valma.fill();

        valma.beginPath();   // 2 сторона
        valma.moveTo(400, 0);
        valma.lineTo(300, 100);
        valma.lineTo(400, 200);
        valma.fillStyle = valm_sk2;
        valma.fill();

        valma.beginPath();   // 3 сторона
        valma.moveTo(0, 200);
        valma.lineTo(100, 100);
        valma.lineTo(300, 100);
        valma.lineTo(400, 200);
        valma.fillStyle = valm_sk3;
        valma.fill();

        valma.beginPath();   // 4 сторона
        valma.moveTo(0, 0);
        valma.lineTo(100, 100);
        valma.lineTo(0, 200);
        valma.fillStyle = valm_sk4;
        valma.fill();
    }
}


    draw() ;
    function razmStrel(color, v, lw){   // Принимает: color - цвет, v - координаты (массив), lw - толщина линии
         let strelka = canvasValma2.getContext('2d');

        if (strelka) {
            // Размерные стрелки
            strelka.strokeStyle = color;
            strelka.lineWidth = lw;
            strelka.beginPath();
            strelka.moveTo(v[0], v[1]);
            strelka.lineTo(v[2], v[3]);
            strelka.stroke();

            strelka.beginPath();
            strelka.lineWidth = 1;
            strelka.moveTo(v[4], v[5]);
            strelka.lineTo(v[6], v[7]);
            strelka.lineTo(v[8], v[9]);
            strelka.stroke();

            strelka.beginPath();
            strelka.lineWidth = 1;
            strelka.moveTo(v[10], v[11]);
            strelka.lineTo(v[12], v[13]);
            strelka.lineTo(v[14], v[15]);
            strelka.stroke();
        }
    }


var inp = document.querySelectorAll('input');

[].forEach.call(inp, function(node,i) {
    let color = 'green',
            v,
            lw = 2;
        switch (i) {
            case 0: v = [0,210, 400,210, 15,207, 0,210, 15,213, 385,207, 400,210, 385,213]; break;
            case 1: v = [100,115, 300,115, 115,112, 100,115, 115,118, 285,112, 300,115, 285,118]; break;
            case 2: v = [120,100, 120,200, 117,115, 120,100, 123,115, 117,185, 120,200, 123,185]; break;
            case 3: v = [410,0, 410,200, 407,15, 410,0, 413,15, 407,185, 410,200, 413,185]; break;
            case 4: v = [300,100, 400,100, 315,97, 300,100, 315,103, 385,97, 400,100, 385,103]; break;
        }
   node.addEventListener("focus", function() {

        draw();
        razmStrel(color, v, lw);
});

   node.addEventListener("blur", draw)



});


</script>

</body>
</html>

Последний раз редактировалось рони, 15.06.2018 в 18:59.
Ответить с цитированием
  #5 (permalink)  
Старый 15.06.2018, 19:14
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

Dilettante_Pro, Спасибо! Я понял идею.
Со стрелками получилось, пришлось ток ещё сначала весь канвас белым прямоугольником залить.
Ответить с цитированием
  #6 (permalink)  
Старый 15.06.2018, 19:37
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

рони, Спасибо! Я не обновлял страницу и увидел пост поздно, поэтому успел исправить код в топике (так бы новым постом свой код сделал).

А в вашем коде меня смущают вот такие моменты:

[].forEach.call(inp, function(node,i) {....
node.addEventListener("blur", draw)...

Мне ещё до этого уровня как минимум год сидеть за JS, а пока я этого не понимаю : (
Поставлю ваш вариант, надеюсь при расширении приложения проблем не будет, но если что откачу к своему варианту.
Ответить с цитированием
  #7 (permalink)  
Старый 15.06.2018, 20:20
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,135

Сообщение от MC-XOBAHCK
[].forEach.call(inp, function(node,i) {....
node.addEventListener("blur", draw)...
тоже самое(почти) что

Цитата:
for (let i = 0; i < inp.length; i++) {
inp[i].addEventListener
node это inp[i].
Ответить с цитированием
  #8 (permalink)  
Старый 15.06.2018, 20:22
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,135

MC-XOBAHCK,
[].forEach.call
Ответить с цитированием
  #9 (permalink)  
Старый 16.06.2018, 15:08
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

После простановки координат для 15 стрелочек (я посчитал), случилась эврика (помидор на голову не падал).
Я понял что мне достаточно всего лишь 3 координаты, чтобы нарисовать стрелочку.

Вывел две таких формулы:
//стрелка вертикально (x, y1, y2):
v = [x,y1, x,y2, (x - 3),(y1 + 30), x,y1, (x + 3),(y1 + 30), (x - 3),(y2 - 30), x,y2, (x + 3),(y2 - 30)]

//стрелка горизонтально (x1, x2, y):
v = [x1,y, x2,y, (x1 + 30),(y - 3), x1,y, (x1 + 30),(y + 3), (x2 - 30),(y - 3), x2,y, (x2 + 30),(y + 3)]

Поэтому решил добавить к стрелкам такие параметры:
size: 'little', 'normal', 'big'
orientation: 'horizontal', 'vertical'

Ориентация - по какой формуле считать координаты. Поставлю на if (orientation == 'horizontal') {...}

Размер - это заменю из формулы значения 3 и 30 (ширина и длина самого указателя стрелки), чтобы на маленьких расстояниях можно было уменьшать, на больших - делать побольше.

Последний раз редактировалось MC-XOBAHCK, 16.06.2018 в 15:18.
Ответить с цитированием
  #10 (permalink)  
Старый 19.06.2018, 11:36
Аватар для MC-XOBAHCK
Профессор
Отправить личное сообщение для MC-XOBAHCK Посмотреть профиль Найти все сообщения от MC-XOBAHCK
 
Регистрация: 06.08.2017
Сообщений: 473

Я идею понял, что можно ещё проще всё сделать. Просидел вчера весь день, но прокачаться до уровня "Говнокодер повелитель стрелочек" не получилось.

Пришёл к тому что теперь нужна только одна точка с координатами x,y.
Ввёл новый параметр - длина стрелочки (в px). Так удобнее. Вторую точку находим через формулу прибавив длину стрелочки к координате x.

Убрал ориентацию (горизонтально/вертикально) и вместо неё добавил rotate в градусах (0-360).
При повороте началось смещение. Как я понял, оно регулируется через трансформ, но пока я к этому не пришёл.

Написал такой онлайн повелитель стрелочек, чтобы понять смещение. Но в нём баг. При указании координат x и y - поведение как будто умножается а не суммируется.
Интерпритатор может оценивать в формуле переменную x2 как помножить на два?

Пока завис на этом баге. До смещения ещё не дошёл, попробовал смотреть поведение меняя параметры через strelka.translate(10, 10); но пока мне баг мешает с этим поработать.
<canvas style="border:1px solid black"></canvas>
<p>Координата X: <input id="x" type="number" min="0" value="0"> Координата Y: <input id="y" type="number" min="0" value="0"></p>
<p>Поворот (Градусы): <input id="deg" type="number" min="0" max="360" value="0"> Длина стрелки (px): <input id="w" type="number" min="0" value="400"></p>

<script>
function risunok() {
    let v = [], lstr, hstr,
        color = 'red',  // цвет стрелочки
        lw = 2,         //толщина линии

        deg = +inputDeg.value,
        x = +inputX.value,
        y = +inputY.value,
        w = +inputWidth.value;

    var canvasRoof = document.querySelector('canvas');
    let strelka = canvasRoof.getContext('2d');
    
    switch (true) { //сами указатели стрелочек - длина и высота (в зависимости от длины стрелочки)
        case (w >= 300):            lstr = 30; hstr = 3; break;
        case (w >= 100 && w <300):  lstr = 20; hstr = 2; break;
        case (w < 100):             lstr = 10; hstr = 2; break;
    }
    
    let x2 = (x + w);//координата x2
    v = [x,y, x2,y, (x + lstr),(y - hstr), x,y, (x + lstr),(y + hstr), (x2 - lstr),(y - hstr), x2,y, (x2 - lstr),(y + hstr)];//координаты
    
    canvasRoof.width = 700;
    canvasRoof.height = 450;

    if (canvasRoof && canvasRoof.getContext) {
        strelka.fillStyle = '#fff';
        strelka.fillRect(0, 0, canvasRoof.width, canvasRoof.height);
        
        strelka.translate(x, y);
        strelka.rotate((Math.PI / 180) * deg); //поворот на .. градусов
        strelka.translate(-x, -y);

        strelka.strokeStyle = color;
        strelka.lineWidth = lw;
        strelka.beginPath();
        strelka.moveTo(v[0], v[1]);
        strelka.lineTo(v[2], v[3]);
        strelka.stroke();

        strelka.beginPath();
        strelka.lineWidth = 1;
        strelka.moveTo(v[4], v[5]);
        strelka.lineTo(v[6], v[7]);
        strelka.lineTo(v[8], v[9]);
        strelka.stroke();
        strelka.fillStyle = color;
        strelka.fill();

        strelka.beginPath();
        strelka.lineWidth = 1;
        strelka.moveTo(v[10], v[11]);
        strelka.lineTo(v[12], v[13]);
        strelka.lineTo(v[14], v[15]);
        strelka.stroke();
        strelka.fillStyle = color;
        strelka.fill();
    }
}

const inputDeg = document.querySelector('#deg');
const inputX = document.querySelector('#x');
const inputY = document.querySelector('#y');
const inputWidth = document.querySelector('#w');

inputDeg.addEventListener('input', () => risunok());
inputX.addEventListener('input', () => risunok());
inputY.addEventListener('input', () => risunok());
inputWidth.addEventListener('input', () => risunok());

risunok();
</script>

Последний раз редактировалось MC-XOBAHCK, 19.06.2018 в 13:19. Причина: Исправил код
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите понять код Navira Общие вопросы Javascript 2 08.09.2016 14:56
Помогите понять) Garet jQuery 4 08.04.2015 20:59
Народ помогите бьюсь уже неделю не магу понять apercot Javascript под браузер 7 06.11.2014 14:08
Помогите с canvas rikod Общие вопросы Javascript 0 08.10.2012 09:48
Анимация. Помогите понять почему не работает. kadurban jQuery 4 08.07.2010 20:50