Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Вопрос по коду связанного с DOM (https://javascript.ru/forum/events/77229-vopros-po-kodu-svyazannogo-s-dom.html)

NeonMan 08.04.2019 19:20

Вопрос по коду связанного с DOM
 
Вот эта кусок кода транслирует анимированный бекграунд сразу в body, а мне нужно что бы транслировал в нужный мне div подскажите пожалуйста где сменить и КАК сменить body на нужный мне div
// init
var maxx = document.body.clientWidth;
var maxy = document.body.clientHeight;
var halfx = maxx / 2;
var halfy = maxy / 2;
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = maxx;
canvas.height = maxy;
var context = canvas.getContext("2d");
var dotCount = 200;
var dots = [];
// create dots
for (var i = 0; i < dotCount; i++) {
  dots.push(new dot());
}

// dots animation
function render() {
  context.fillStyle = "#000000";
  context.fillRect(0, 0, maxx, maxy);
  for (var i = 0; i < dotCount; i++) {
    dots[i].draw();
    dots[i].move();
  }
  requestAnimationFrame(render);
}

// dots class
// @constructor
function dot() {
  
  this.rad_x = 2 * Math.random() * halfx + 1;
  this.rad_y = 1.2 * Math.random() * halfy + 1;
  this.alpha = Math.random() * 360 + 1;
  this.speed = Math.random() * 100 < 50 ? 1 : -1;
  this.speed *= 0.1;
  this.size = Math.random() * 5 + 1;
  this.color = Math.floor(Math.random() * 256);
  
}

// drawing dot
dot.prototype.draw = function() {
  
  // calc polar coord to decart
  var dx = halfx + this.rad_x * Math.cos(this.alpha / 180 * Math.PI);
  var dy = halfy + this.rad_y * Math.sin(this.alpha / 180 * Math.PI);
  // set color
  context.fillStyle = "rgb(" + this.color + "," + this.color + "," + this.color + ")";
  // draw dot
  context.fillRect(dx, dy, this.size, this.size);
  
};

// calc new position in polar coord
dot.prototype.move = function() {
  
  this.alpha += this.speed;
  // change color
  if (Math.random() * 100 < 50) {
    this.color += 1;
  } else {
    this.color -= 1;
  }
  
};

// start animation
render();

Rise 08.04.2019 20:02

var myDiv = document.querySelector('#myDivId'); и все document.body заменить на myDiv

Malleys 08.04.2019 20:14

Цитата:

Сообщение от Rise
document.body заменить на myDiv

Я бы выделил отдельный класс DotAnimation

https://codepen.io/Malleys/pen/XQNpXK

NeonMan 08.04.2019 20:22

Пишет что
TypeError: Cannot read property 'clientWidth' of null для var myDiv

Rise 08.04.2019 20:35

Malleys, пойдет.
NeonMan, нет элемента с таким id значит.

рони 08.04.2019 20:38

Цитата:

Сообщение от NeonMan
if (Math.random() * 100 < 50)

:-?
if (Math.random() < .5) {

NeonMan 08.04.2019 20:42

Дело в том, что я запускаю эту функцию в компоненте react, а этот компонент вырисовывает блок в который должна идти анимация. Может мне как то запустить эту функцию после того, как компонент отрисовал нужный блок. Не очень понятно с импортом тут.
в bg-animation.js лежит вариант от Malleys

import React, { Component } from 'react';
import './home.css';
import * as animation from './bg-animation.js';

export default class Home extends Component {
	
	componentDidMount() {
		console.log('DOM уже на странице')
	};

	render() {		
		return ( 
		<div id="app">

		</div>		 
		)
	}	
};

NeonMan 08.04.2019 21:01

Работает в таком виде только, если без импорта, спасибо

import React, { Component } from 'react';
import './home.css';


function DotAnimation(element) {
  var maxx = element.offsetWidth;
  var maxy = element.offsetHeight;
  var halfx = maxx / 2;
  var halfy = maxy / 2;
  var canvas = document.createElement("canvas");
  element.appendChild(canvas);
  canvas.width = maxx;
  canvas.height = maxy;
  var context = canvas.getContext("2d");
  var dotCount = 200;
  var dots = [];
  // create dots
  for (var i = 0; i < dotCount; i++) {
    dots.push(new Dot(halfx, halfy));
  }

  // dots animation
  function render() {
    context.fillStyle = "#000000";
    context.fillRect(0, 0, maxx, maxy);
    for (var i = 0; i < dotCount; i++) {
      dots[i].draw(context);
      dots[i].move();
    }
    requestAnimationFrame(render);
  }
  render();
}
// dots class
// @constructor
function Dot(halfx, halfy) {
  this.halfx = halfx;
  this.halfy = halfy;
  this.rad_x = 2 * Math.random() * this.halfx + 1;
  this.rad_y = 1.2 * Math.random() * this.halfy + 1;
  this.alpha = Math.random() * 360 + 1;
  this.speed = Math.random() * 100 < 50 ? 1 : -1;
  this.speed *= 0.1;
  this.size = Math.random() * 5 + 1;
  this.color = Math.floor(Math.random() * 256);
}

// drawing dot
Dot.prototype = {
  draw: function(context) {
    // calc polar coord to decart
    var dx = this.halfx + this.rad_x * Math.cos(this.alpha / 180 * Math.PI);
    var dy = this.halfy + this.rad_y * Math.sin(this.alpha / 180 * Math.PI);
    // set color
    context.fillStyle =
      "rgb(" + this.color + "," + this.color + "," + this.color + ")";
    // draw dot
    context.fillRect(dx, dy, this.size, this.size);
  },

  // calc new position in polar coord
  move: function() {
    this.alpha += this.speed;
    // change color
    if (Math.random() * 100 < 50) {
      this.color += 1;
    } else {
      this.color -= 1;
    }
  }
};

export default class Home extends Component {
	
	componentDidMount() {
		console.log('DOM уже на странице');
		new DotAnimation(document.getElementById("app"));
	};

	render() {		
		return ( 
		<div id="app">
 
		</div>		 
		)
	}	
};

Malleys 08.04.2019 21:06

Цитата:

Сообщение от NeonMan
Работает в таком виде только, если без импорта, спасибо

dсё-таки надо с import-ом... Вы не знали про React ref?

https://codesandbox.io/s/m7o21ym6pj

NeonMan 08.04.2019 21:29

Цитата:

Сообщение от Malleys (Сообщение 506211)
dсё-таки надо с import-ом... Вы не знали про React ref?

https://codesandbox.io/s/m7o21ym6pj

Не очень понимаю что делает canvasRoot где то есть подробное описание этого?
И есть ли на этом форуме ветка с React JS ? ^^

Malleys 08.04.2019 21:43

Цитата:

Сообщение от NeonMan
canvasRoot

canvasRoot является ссылкой на представителя HTMLElement, который соответствует виртуальному элементу <div id="app" ref="canvasRoot" />;(это синтаксический сахар для React.createElement("div", { id: "app", ref: "canvasRoot" });). Т. е. canvasRoot указывает на настоящий элемент, вставленный в DOM, который и передаётся в new DotAnimation(canvasRoot);

Цитата:

Сообщение от NeonMan
Не очень понимаю что делает canvasRoot где то есть подробное описание этого?

Это название придумал я, вы можете назвать как угодно! Это значение атрибута ref указывается у React элемента React.createElement("div", { id: "app", ref: "canvasRoot" });

И затем вызов ReactDOM.findDOMNode(this.refs.canvasRoot); указывает на настоящий элемент, соответствующий React элементу.

NeonMan 08.04.2019 21:53

А вот же работает и без React ref

https://codesandbox.io/s/o1jyymlq49

NeonMan 08.04.2019 21:59

Я понял, с помощью этой строчки
const canvasRoot = ReactDOM.findDOMNode(this.refs.canvasRoot);

Указываем на элемент из ДОМ для функции.
Но мне кажется такую строчку написать легче, не?
document.querySelector("#animation")

Или бывают случаи где подход через ref оправдан?

Malleys 08.04.2019 22:03

Цитата:

Сообщение от NeonMan
А вот же работает и без React ref, выходит он не нужен?

Да, работает и не работает, как надо, вы не сможете использовать этот компонент более одного раза, поскольку document.querySelector("#app") указывает на один и тот же элемент.

document.querySelector("#app") ищет элемент, зачем вам его искать, когда вы его сами создаёте.

Чтобы это правильно работало вам нужно это компонент изолировать от остальной части DOM при помощи Shadow DOM API...

Я думаю, если вы решили использовать React.js, то нужно использовать все его возможности, а не только часть, а остальное пытаться изобрести заново. Да, ссылка на настоящий элемент может быть нужна, и такая возможность предоставляется!

NeonMan 08.04.2019 22:12

А зачем компонент изолировать от основного DOM ?
Указывать на элемент через ref я то не против, просто хочется знать в чем разница. Тем более что в этом варианте каждый раз нужно подключать к компоненту => import ReactDOM from "react-dom";

рони 08.04.2019 22:15

Malleys,
можно ли пример где document.querySelector("#app") не работает?

Malleys 08.04.2019 22:48

Вот пример, где ещё не было React-а, тот самый мой первый пример https://codepen.io/Malleys/pen/XQNpXK

Тут класс DotAnimation может использоваться много раз, для каждого элемента свой селектор
new DotAnimation(document.getElementById("app"));
new DotAnimation(document.getElementById("app2"));


Если вы замените "app2" на "app", то второй не будет работать.

Цитата:

Сообщение от рони
можно ли пример где document.querySelector("#app") не работает?

Так ещё один React элемент Home создайте... вот добавил второй к примеру с ref https://codesandbox.io/s/m7o21ym6pj работает, как ожидается

пример с document.querySelector("#app") https://codesandbox.io/s/rryjlyjrr4 работает, не так как ожидается

Обратите внимание, что сanvas вставлен не туда!

Цитата:

Сообщение от NeonMan
А зачем компонент изолировать от основного DOM ?

Именно для того, чтобы не происходило такого, что разные элементы разных компонент перепутаны.

Цитата:

Сообщение от NeonMan
Тем более что в этом варианте каждый раз нужно подключать к компоненту => import ReactDOM from "react-dom";

он импортируется только один раз, это ссылка на один и тот же ReactDOM

рони 08.04.2019 23:08

Цитата:

Сообщение от Malleys
Обратите внимание, что сanvas вставлен не туда!

спасибо, сам это не заметил.

NeonMan 08.04.2019 23:21

Спасибо за подробный ответ

рони 08.04.2019 23:25

Цитата:

Сообщение от NeonMan
есть ли на этом форуме ветка с React JS ?

на данный момент такого подразела нет, есть Библиотеки/Тулкиты/Фреймворки


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