Используйте холст для реализации движения прямоугольников (точек, линий, поверхностей) (1)

внешний интерфейс Canvas
Используйте холст для реализации движения прямоугольников (точек, линий, поверхностей) (1)

Это 7-й день моего участия в Gengwen Challenge.Подробности о мероприятии:Обновить вызов

предисловие

Возможно, вы видели много движущихся картинок и прямоугольников на холсте. Но зачем мне писать такую ​​статью, ведь автор сделал движение под 3D графику. Это включает в себя перемещение ребра куба, грани и перемещение точки многоугольника. В последнее время я пишу статьи на тему холста, думаю сделать на него обзор, прочитав эту статью, вы сможете это узнать, перемещая точку прямоугольника, линию и движение всей поверхности. Эта статья от мелкой до глубокой, я надеюсь, что вы терпеливо прочитали ее.

движение лица

Представьте себе реализацию мобильных функций под холстом. Первым шагом должно быть создание холста и добавление события перемещения на холст, чтобы мы могли получать положение нашей мыши в режиме реального времени, а затем нам просто нужно продолжать очищать холст, а затем перерисовывать прямоугольник. Это нормально, и движение поверхности изначально реализовано. Движение, которое я напишу ниже, перепишет это, вот быстрая и простая версия.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = 100;
const height = 100;
drawRect();
function drawRect(x = 10,y = 10, scale = 1) {
    ctx.clearRect( 0, 0, 1800, 800 );
    const halfwidth = width * scale / 2;
    const halfheight = height * scale / 2;
    ctx.strokeRect(x - halfwidth, y - halfheight,width * scale, height * scale)
}
let isMove =  true;
canvas.addEventListener('mousemove',(e)=>{
    if(!isMove) {
        return 
    }
    const x = e.clientX;
    const y = e.clientY;
    drawRect(x,y)
})
canvas.addEventListener('click',(e)=> {
    isMove = !isMove;
});

Переменная Ismove - это переключатель. Мы не можем перемещать все время, оно слишком утомительно, а щелчок мыши будет пауза. Для вышеупомянутой, почему х - полувидность, Y - Halfheight

Позвольте мне объяснить вам здесь: strokeRect рисуется из левого верхнего угла прямоугольника, но я хочу поместить прямоугольник в центр мыши, чтобы его можно было идеально отобразить, вычитая ширину и высоту.

движение точек

Первый вопрос? Как мы узнаем, какую точку мы выбрали?Здесь я сделал простое суждение, оценивая положение щелчка мыши и сравнивая положение каждой точки прямоугольника, чтобы увидеть, какая из них находится ближе всего к целевой точке. Поскольку движение нашей 2-й точки на самом деле заключается в поиске сегмента линии, связанного с этой точкой, поэтому нам нужно только регенерировать связанный сегмент линии, но есть ли более сложное место? Просто сделать полукруг? Если мы переместим точку излома полуокружности, это влечет за собой изменение дуги, которая может стать эллиптической дугой или быть выражена кривой Безье второго или третьего порядка. Кроме того, перемещение фигуры и других фигур на холсте образует разрез? Алгоритм тоже надо урезать? На самом деле вы можете использоватьClipperЧтобы найти дружбу и отличие, заинтересованные студенты могут узнать об этом сами, но это не то, что мы хотим объяснить в этой статье. Все примеры в этой статье (поддерживаются только прямые линии, также известные как LineSegment).

Хорошо, наш первый шаг — перевыразить прямоугольник, потому что он недостаточно общий и точный, — перевыразить четырехугольник, прямоугольник и квадрат — это просто специальные столбцы. Вот я даю причину? Почему?В очень простом случае, перемещая точку четырехугольника, это может стать следующим:

Xnip2021-06-22_23-02-28.png

ok Чтобы выразить следующее, мы создаем новый класс Point2d и используем экземпляр для представления каждой точки на холсте.

class Point2d {
    constructor(x,y) {
        this.x = x || 0;
        this.y = y || 0;
    }
    clone() {
        return this.constructor(this.x, this.y);
    }
    add(v) {
        this.x += v.x;
        this.y += v.y
        return this;
    }
   random() {
        this.x = Math.random() *1800;
        this.y = Math.random() * 800;
        return this
    }
}

Далее мы просто добавляем длину и ширину прямоугольника к положению мыши на холсте и рисуем прямоугольник. код показывает, как показано ниже:

function drawFourPolygon(x, y ,width = 50, height = 50) {
    ctx.clearRect( 0, 0, 1800, 800 );
    ctx.beginPath();
    ctx.moveTo(x- width /2, y - height/2)
    ctx.lineTo(x+ width / 2, y -height/2 )
    ctx.lineTo(x+ width / 2, y + height/2 )
    ctx.lineTo(x - width / 2, y + height/2 )
    ctx.closePath()
    ctx.stroke()
}

Чтобы сделать взаимодействие более совершенным, первый щелчок мышью определяет начальную точку движения, а затем движение мыши является конечной точкой движения, таким образом определяется вектор. Здесь для того, чтобы было нагляднее при движении, я добавил функцию пунктирной линии, код такой

function drawDashLine(start, end) {
      if (!start || !end) {
          return
      }
      ctx.strokeStyle = 'red';
      ctx.setLineDash( [5, 10] );
      ctx.beginPath();  
      ctx.moveTo( start.x, start.y );
      ctx.lineTo( end.x, end.y );
      ctx.closePath()
      ctx.stroke();
  }

Здесь используется значение холста параметра api setLineDash.Расстояние сплошной линии равно 5, а расстояние пробела равно 10. Движение вперед и назад таким образом образует пунктирную линию. start и end — это начальная точка, определяемая щелчком мыши, и конечная точка, когда мышь продолжает движение. Здесь небольшое напоминание, что сначала я нарисовал пунктирную линию, а потом прямоугольник, когда двигал мышкой, и что? У нас все еще есть сплошные линии для прямоугольников. Здесь мы изменили код рисования прямоугольника или восстановили пунктирную линию.

код показывает, как показано ниже:

 ctx.setLineDash([]); 

ОК. Общее взаимодействие отключено. Позвольте мне сначала показать вам эффект:

Вы чувствуете себя немного хахаха? Судя по картинке, это все еще общее движение, а не движение точек.Поскольку графика, которую я нарисовал, рисуется точкой щелчка мыши, чтобы нарисовать прямоугольник, в моей следующей статье будет представлено движение точек неправильного многоугольника.Эта статья Давайте все же предположим, что я двигаюсьточка вверху справа. OkМы получаем вектор перемещения из начальной и конечной точек перемещения, поэтому просто добавляем точку для перемещения к этому вектору. Таким образом, мы реализуем движение точки.

 const moveVec = end.clone().sub(start);
 const rightTop = new Point2d(x+ width / 2, y - height/2).clone().add(moveVec)

Здесь я изменил точку в правом верхнем углу, но есть проблема, что мы нажимаем на одну и ту же функцию, поэтому мы должны добавить переключатель, чтобы судить, в основном, чтобы интерпретировать, является ли это первым щелчком или перемещать код следующим образом. :

ctx.lineTo(isSelect ? rightTop.x : x+ width / 2, isSelect ? rightTop.y : y height/2)

// 看下click和move 事件 开关就是isSelect这个变量
canvas.addEventListener('mousemove',(e)=>{
    if(!isMove) {
        return 
    }
    const x = e.clientX;
    const y = e.clientY;
    clearRect();
    end = new Point2d(x,y);
    drawDashLine(start,end);
    drawFourPolygon(start)
})
canvas.addEventListener('click',(e)=> {
    // 这是一个每次清除画布的函数
    clearRect()
    isMove = !isMove;
    const x = e.clientX;
    const y = e.clientY;
    start  = new Point2d(x,y);
    drawFourPolygon(start)
    isSelect = true;
});

Схема эффекта выглядит следующим образом:

Jun-23-2021 23-00-57.gif

Ха-ха-ха, он очень шелковистый и гладкий?Я обнаружил, что рисование на холсте по-прежнему очень хорошо. Но есть еще проблема, для определения результата, глядя на приведенный выше код определяем, что результат проблемный. В итоге я удержал нажатой клавишу Alt, чтобы убедиться, что результат был идеальным, код здесь не показан.

движение линии

При движении точек движение линий отображается очень просто. Движение линии на самом деле является движением соответствующей точки. Возьмем в качестве примера строку справа: Код переписывается следующим образом:

function drawFourPolygon( point, width = 50, height = 50) {
    if(!point) {
        return 
    }
    ctx.strokeStyle = 'black'
    ctx.setLineDash([]); 
    ctx.beginPath();
    const { x, y } = point;
    const moveVec = end.clone().sub(start);
    // 其实就是 右上和右下这两个点同时移动
    const rightTop = new Point2d(x+ width / 2, y - height/2).clone().add(moveVec)
    const rightBottom = new Point2d(x+ width / 2, y + height/2).clone().add(moveVec)
    ctx.moveTo(x- width /2, y - height/2)
    ctx.lineTo(isSelect ? rightTop.x : x+ width / 2, isSelect ? rightTop.y : y - height/2)
    ctx.lineTo(isSelect ? rightBottom.x : x+ width / 2, isSelect ? rightBottom.y : y + height/2) 
    ctx.lineTo(x - width / 2, y + height/2 )
    ctx.closePath()
    ctx.stroke()
  }

Мы смотрим вниз на рендеринг:

Jun-23-2021 23-13-20.gif

Суммировать

В этой статье в основном представлены самые основные изменения в 2D-графике.переехать, будь то движение линии или движение поверхности, в конечном счете является движением точки. Фактически, в дополнение к векторному представлению движение также может быть представлено матрицей, или наши команды, такие как вращение, перемещение, масштабирование и т. д., могут быть представлены изменениями матрицы. Наконец, я хотел бы поблагодарить всех за то, что увидели конец. Кодировать слова непросто. Если это будет вам полезно, пожалуйста, поставьте лайк и подпишитесь. Ваша поддержка — самая большая мотивация для меня продолжать обновлять хорошие статьи. Весь код у меняgithubначальство. Добро пожаловать в звезду.