Анимация холста, проблема с расчетами математики в моем коде JavaScript -- javascript поле с участием algorithm поле с участием canvas поле с участием javascript-objects пол Связанный проблема

Canvas animation, issue with Math calculations in my javascript code


0
vote

проблема

русский

<Сильная> идея:

Привет, это мой первый эксперимент с холстом анимацией. Я не уверен, что эта концепция уже существует, но я назвал мою версию «Двухугосударственная анимация». Идея такова: карта создается с тремя подмарами для каждого объекта на экране. Одна из подпунктов содержит текущие свойства состояния (анимирующего объекта), второй удерживает конечный пункт назначения (анимирующего объекта), а третий для разделенных шагов для обеспечения объекта (на экране) достигает своего конечного пункта назначения В количестве кадров, установленных в `framesforchange.

<Сильная> проблема:

Уведомление, как прогресс анимации, объекты постепенно отодвигаются вниз вправо, но числа для оси X и Y продолжают расти. Я знаю, что я генерирую случайное число, чтобы ограничить его в ширину (x) и высоте (y) в области просмотра. Почему это происходит? Как я могу это исправить?

код:

Если у вас есть какие-либо предложения о том, как я могу сделать это более эффективным (или, в первую очередь, исправить проблему [упомянутой выше]), пожалуйста, укажите его в вашем ответе или в комментариях. Спасибо.

 <Код> window.addEventListener('load', initializeCanvasTwo());    function initializeCanvasTwo() {    var canvas, c, map = {},      framesForChange = 360;      initializeCanvas();    resizeCanvas();    initializeMapping();    draw();      window.addEventListener('resize', function() {      resizeCanvas();    });      function initializeCanvas() {      canvas = document.getElementById('canvasTwo');      c = canvas.getContext('2d');    }      function resizeCanvas() {      canvas.width = window.innerWidth;      canvas.height = window.innerHeight;      c.width = window.innerWidth;      c.height = window.innerHeight;    }      function initializeMapping() {      var n = Math.floor(window.innerWidth * window.innerHeight / 20000);      for (var i = 0; i < n; i++) {        map[i] = {          current: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          final: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          increment: {            }        };        map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;      }    }      function getRandomX() {      return Math.floor(Math.random() * window.innerWidth);    }      function getRandomY() {      return Math.floor(Math.random() * window.innerHeight);    }      function updateMap() {      var n = Object.keys(map).length;      for (var i = 0; i < n; i++) {        if (map[i].final.startX - map[i].current.startX < map[i].increment.startXIncrement) {          //startX transition complete: set new destination...          map[i].final.startX = getRandomX();          map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        } else {          map[i].current.startX += map[i].increment.startXIncrement;        }          if (map[i].final.startY - map[i].current.startY < map[i].increment.startYIncrement) {          //startY transition complete: set new destination...          map[i].final.startY = getRandomY();          map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        } else {          map[i].current.startY += map[i].increment.startYIncrement;        }          if (map[i].final.endX - map[i].current.endX < map[i].increment.endXIncrement) {          //endX transition complete: set new destination...          map[i].final.endX = getRandomX();          map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        } else {          map[i].current.endX += map[i].increment.endXIncrement;        }          if (map[i].final.endY - map[i].current.endY < map[i].increment.endYIncrement) {          //endY transition complete: set new destination...          map[i].final.endY = getRandomY();          map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;        } else {          map[i].current.endY += map[i].increment.endYIncrement;        }      }    }      function draw() {      c.clearRect(0, 0, window.innerWidth, window.innerHeight);      c.strokeStyle = 'blue';      var n = Object.keys(map).length;      for (var i = 0; i < n; i++) {        c.beginPath();        c.moveTo(map[i].current.startX, map[i].current.startY);        c.lineTo(map[i].current.endX, map[i].current.endY);        c.stroke();        c.closePath();      }      updateMap();      requestAnimationFrame(draw);    }  }  
 <Код> html,  body {    margin: 0;    padding: 0;  }  canvas {    width: 100%;    height: 100%;    margin-bottom: -4px;  }  
 <Код> <canvas id="canvasTwo"></canvas>  
Английский оригинал

The idea:

Hi, this is my first experiment with canvas animation. I'm not sure if this concept already exists but I've dubbed my version "two-state animation". The idea is this: A map is created with three sub-maps for each object on-screen. One of the sub-map holds the current state properties (of an animating object), the second holds the final destination (of an animating object), and the third for divided increments to ensure the object (on-screen) reaches its final destination in the number of frames set in `framesForChange.

The problem:

Notice, as the animation progresses, the objects are gradually pushed down to the bottom right but the numbers for x and y axis continue to grow. I'm aware that I'm generating random number to confine it within the width (x) and height (y) of the viewport. Why is this happening? How can I fix it?

The code:

If you have any suggestions for how I could make this more efficient (or, more primarily, fix the problem [mentioned above]), please mention it in your answer or in the comments. Thank you.

window.addEventListener('load', initializeCanvasTwo());    function initializeCanvasTwo() {    var canvas, c, map = {},      framesForChange = 360;      initializeCanvas();    resizeCanvas();    initializeMapping();    draw();      window.addEventListener('resize', function() {      resizeCanvas();    });      function initializeCanvas() {      canvas = document.getElementById('canvasTwo');      c = canvas.getContext('2d');    }      function resizeCanvas() {      canvas.width = window.innerWidth;      canvas.height = window.innerHeight;      c.width = window.innerWidth;      c.height = window.innerHeight;    }      function initializeMapping() {      var n = Math.floor(window.innerWidth * window.innerHeight / 20000);      for (var i = 0; i < n; i++) {        map[i] = {          current: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          final: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          increment: {            }        };        map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;      }    }      function getRandomX() {      return Math.floor(Math.random() * window.innerWidth);    }      function getRandomY() {      return Math.floor(Math.random() * window.innerHeight);    }      function updateMap() {      var n = Object.keys(map).length;      for (var i = 0; i < n; i++) {        if (map[i].final.startX - map[i].current.startX < map[i].increment.startXIncrement) {          //startX transition complete: set new destination...          map[i].final.startX = getRandomX();          map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        } else {          map[i].current.startX += map[i].increment.startXIncrement;        }          if (map[i].final.startY - map[i].current.startY < map[i].increment.startYIncrement) {          //startY transition complete: set new destination...          map[i].final.startY = getRandomY();          map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        } else {          map[i].current.startY += map[i].increment.startYIncrement;        }          if (map[i].final.endX - map[i].current.endX < map[i].increment.endXIncrement) {          //endX transition complete: set new destination...          map[i].final.endX = getRandomX();          map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        } else {          map[i].current.endX += map[i].increment.endXIncrement;        }          if (map[i].final.endY - map[i].current.endY < map[i].increment.endYIncrement) {          //endY transition complete: set new destination...          map[i].final.endY = getRandomY();          map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;        } else {          map[i].current.endY += map[i].increment.endYIncrement;        }      }    }      function draw() {      c.clearRect(0, 0, window.innerWidth, window.innerHeight);      c.strokeStyle = 'blue';      var n = Object.keys(map).length;      for (var i = 0; i < n; i++) {        c.beginPath();        c.moveTo(map[i].current.startX, map[i].current.startY);        c.lineTo(map[i].current.endX, map[i].current.endY);        c.stroke();        c.closePath();      }      updateMap();      requestAnimationFrame(draw);    }  }
html,  body {    margin: 0;    padding: 0;  }  canvas {    width: 100%;    height: 100%;    margin-bottom: -4px;  }
<canvas id="canvasTwo"></canvas>
</div
           

Список ответов

1
 
vote
vote
Лучший ответ
 

Основная проблема заключается в <код> if условий.

Вы проверяете, если финальный ток меньше, чем приращение. Но когда X пытается перемещать влево или y opward (, что означает запуск и GT; Final ), вы создаете новые значения для них. Так что это разрешено только идти вправо и снизу. ( Решить это, вы должны использовать <код> Math.abs с обеих сторон, если, но это будет ухудшить производительность даже дальше )

Как незначительные улучшения, которые вы должны использовать массив для map , и поскольку все элементы принимают те же кадры для завершения их анимации, вы не должны проверять, добрался ли каждая точка, но подсчитав кадры и Обновите конечные позиции все сразу.

 <Код> window.addEventListener('load', initializeCanvasTwo());    function initializeCanvasTwo() {    var canvas, c, map = [],      framesForChange = 360,      currentFrame = 360;      initializeCanvas();    resizeCanvas();    initializeMapping();    draw();      window.addEventListener('resize', function() {      resizeCanvas();    });      function initializeCanvas() {      canvas = document.getElementById('canvasTwo');      c = canvas.getContext('2d');    }      function resizeCanvas() {      canvas.width = window.innerWidth;      canvas.height = window.innerHeight;      c.width = window.innerWidth;      c.height = window.innerHeight;    }      function initializeMapping() {      var n = Math.floor(window.innerWidth * window.innerHeight / 20000);      for (var i = 0; i < n; i++) {        map[i] = {          current: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          final: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          increment: {            }        };        map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;      }    }      function getRandomX() {      return Math.floor(Math.random() * window.innerWidth);    }      function getRandomY() {      return Math.floor(Math.random() * window.innerHeight);    }      function updateMap() {      var n = map.length;      currentFrame = --currentFrame || framesForChange;      if (currentFrame == framesForChange){        // create new values        for (var i = 0; i < n; i++) {          map[i].final.startX = getRandomX();          map[i].final.startY = getRandomY();          map[i].final.endX = getRandomX();          map[i].final.endY = getRandomY();                    map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;          map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;          map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;          map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;        }      }      for (var i = 0; i < n; i++) {          map[i].current.startX += map[i].increment.startXIncrement;          map[i].current.startY += map[i].increment.startYIncrement;          map[i].current.endX += map[i].increment.endXIncrement;          map[i].current.endY += map[i].increment.endYIncrement;      }    }      function draw() {      c.clearRect(0, 0, window.innerWidth, window.innerHeight);            var n = map.length;      c.strokeStyle = 'blue';      for (var i = 0; i < n; i++) {        c.beginPath();        c.moveTo(map[i].current.startX, map[i].current.startY);        c.lineTo(map[i].current.endX, map[i].current.endY);        c.stroke();        c.closePath();      }      updateMap();      requestAnimationFrame(draw);    }  }  
 <Код> html,  body {    margin: 0;    padding: 0;  }  canvas {    width: 100%;    height: 100%;    margin-bottom: -4px;  }  
 <Код> <canvas id="canvasTwo"></canvas>  
 

The major problem is with the if conditions.

You check if the final - current is less than the increment. But when the x tries to move leftwards or the y upwards (which means start > final) then you create new values for them. So it is only allowed to go to the right and bottom. (to solve this you should use Math.abs on both sides of the if, but that would degrade performance even further)

As slight improvements you should use an array for the map and since all elements take the same frames to complete their animation you should not check if each point has reached its destination, but count the frames and update the end positions all at once.

window.addEventListener('load', initializeCanvasTwo());    function initializeCanvasTwo() {    var canvas, c, map = [],      framesForChange = 360,      currentFrame = 360;      initializeCanvas();    resizeCanvas();    initializeMapping();    draw();      window.addEventListener('resize', function() {      resizeCanvas();    });      function initializeCanvas() {      canvas = document.getElementById('canvasTwo');      c = canvas.getContext('2d');    }      function resizeCanvas() {      canvas.width = window.innerWidth;      canvas.height = window.innerHeight;      c.width = window.innerWidth;      c.height = window.innerHeight;    }      function initializeMapping() {      var n = Math.floor(window.innerWidth * window.innerHeight / 20000);      for (var i = 0; i < n; i++) {        map[i] = {          current: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          final: {            startX: getRandomX(),            startY: getRandomY(),            endX: getRandomX(),            endY: getRandomY()          },          increment: {            }        };        map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;        map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;        map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;        map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;      }    }      function getRandomX() {      return Math.floor(Math.random() * window.innerWidth);    }      function getRandomY() {      return Math.floor(Math.random() * window.innerHeight);    }      function updateMap() {      var n = map.length;      currentFrame = --currentFrame || framesForChange;      if (currentFrame == framesForChange){        // create new values        for (var i = 0; i < n; i++) {          map[i].final.startX = getRandomX();          map[i].final.startY = getRandomY();          map[i].final.endX = getRandomX();          map[i].final.endY = getRandomY();                    map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;          map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;          map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;          map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;        }      }      for (var i = 0; i < n; i++) {          map[i].current.startX += map[i].increment.startXIncrement;          map[i].current.startY += map[i].increment.startYIncrement;          map[i].current.endX += map[i].increment.endXIncrement;          map[i].current.endY += map[i].increment.endYIncrement;      }    }      function draw() {      c.clearRect(0, 0, window.innerWidth, window.innerHeight);            var n = map.length;      c.strokeStyle = 'blue';      for (var i = 0; i < n; i++) {        c.beginPath();        c.moveTo(map[i].current.startX, map[i].current.startY);        c.lineTo(map[i].current.endX, map[i].current.endY);        c.stroke();        c.closePath();      }      updateMap();      requestAnimationFrame(draw);    }  }
html,  body {    margin: 0;    padding: 0;  }  canvas {    width: 100%;    height: 100%;    margin-bottom: -4px;  }
<canvas id="canvasTwo"></canvas>
</div
 
 
 
 

Связанный проблема

0  Почему угловые $ не удаляют старое значение?  ( Why is angular scope not removing old value ) 
У меня есть следующий контроллер <код> angular.module('publicApp') .controller('URLSummaryCtrl', function ($scope, $location, Article, $rootScope, $timeou...

0  Asp.net внутри тега скрипта  ( Asp net inside a script tag ) 
Я пытаюсь получить некоторую работу с некоторыми JavaScript, который делает график в зависимости от предоставленной вами информации. Я говорю о Это <код...

-2  Динамический фон WordPress на основе изображений слайдера  ( Dynamic wordpress background based on slider images ) 
Я использую NivoSlider на WordPress, и я хочу, чтобы фона моей домашней страницы измениться на основе текущего изображения слайда! У меня нет опыта работы в J...

0  По какой-то причине мой нижний колонтитул не очень мобильный  ( For some reason my footer isnt very mobile friendly ) 
90% моего веб-сайта мобильнее (все равно размера), но по какой-то причине мой нижний колонтитул в основном полностью отрезан на мобильном телефоне. То, как ...

8  Предотвращение DOM XSS  ( Preventing dom xss ) 
Мы недавно мы на борту чужого кода, который с тех пор был проверен, и не удалось, для атаки DOM XSS. В основном фрагменты URL передаются непосредственно в сел...

3  OnleftClick & OnrightClick JavaScript Функции  ( Onleftclick onrightclick javascript functions ) 
В моем боковом коде сервера я динамически строим таблицу и именно сейчас я добавляю следующий код, чтобы обрабатывать Щелчок строки. <код> tr.Attributes.Add...

0  Как добавить значение для массива после проверки другого массива  ( How to add value to array after checking another array ) 
У меня есть два массива как таковые: <код> UserGroupUser[{Id:"1",UserId:"2",UserGroupId"1"}, {Id:"2",UserId:"3",UserGroupId"1"}, {Id:...

1  Расширение фона с помощью JavaScript  ( Extending a background using javascript ) 
У меня есть страница, которая выглядит так <код> ----------------------------------- | ************* | | ************* ...

13  Как перечислить все зарегистрированные события узла DOM с помощью JavaScript?  ( How to list all registered events of a dom node using javascript ) 
Я могу добавить или удалить обработчик событий для узла DOM. Можно ли выяснить все зарегистрированные обработчики событий данного узла DOM? Я имею в виду прям...

0  Как создать элемент DOM в другой шаблон?  ( How to create a dom element to another template ) 
У меня есть пример сценария. Короче говоря - если вы нажмете на «Добавить» создают ряд новых элементов, так как он был заполнен полями. Используемый ионный. Н...

1  Путь нужна модуль в узле JS Работа в Windows, но не в Linux  ( Path of require module in node js work in windows but not in linux ) 
У меня это в моем коде <Код> var queries = require('./Queries.js'); При запуске сервера узла в Windows CMD в порядке. Я клонировать пролей в сервере Li...

1  Поток данных в реальном времени на веб-страницу  ( Stream realtime data to web page ) 
Я работаю над проектом, где мы хотим отслеживать данные на канале Comm и предоставить обратную связь на веб-страницу. Данные будут прочитаны процессом, работа...

1  Как я могу выбрать вторую кнопку Отмена, а не первым?  ( How can i select the second cancel button instead of the first ) 
Я хочу отменить второй элемент строки вместо первого. Ниже приведен какой-то пример код для 2 позиций: <код> <div class="screenlet-body"> <form na...

1  Изолированные Директива охвата с двусторонним связыванием не отражает изменения в объеме контроллера  ( Isolated scope directive with two way binding doesnt reflect changes in control ) 
<Сильное> Сводка: При попытке изменить переменную область (массив), которая была установлена ​​для двухстороннего привязки данных в пределах выделенной дир...

0  Обратный вызов для GridView Yii2 CheckboxColumn  ( Callback for yii2s gridview checkboxcolumn ) 
У меня есть <код> GridView (yii2) и один из столбцов - это логический тип данных. Я хочу быть в состоянии переключить это значение и сохранить его в моей баз...

Связанный проблема

0  Почему угловые $ не удаляют старое значение? 
0  Asp.net внутри тега скрипта 
-2  Динамический фон WordPress на основе изображений слайдера 
0  По какой-то причине мой нижний колонтитул не очень мобильный 
8  Предотвращение DOM XSS 
3  OnleftClick & OnrightClick JavaScript Функции 
0  Как добавить значение для массива после проверки другого массива 
1  Расширение фона с помощью JavaScript 
13  Как перечислить все зарегистрированные события узла DOM с помощью JavaScript? 
0  Как создать элемент DOM в другой шаблон? 
1  Путь нужна модуль в узле JS Работа в Windows, но не в Linux 
1  Поток данных в реальном времени на веб-страницу 
1  Как я могу выбрать вторую кнопку Отмена, а не первым? 
1  Изолированные Директива охвата с двусторонним связыванием не отражает изменения в объеме контроллера 
0  Обратный вызов для GridView Yii2 CheckboxColumn