Как я могу анимировать трассировку прямоугольника SVG с помощью JavaScript? - PullRequest
0 голосов
/ 21 января 2019

Для игры, над которой я работаю,

Я хотел бы иметь возможность рисовать прямоугольник SVG; используя процентное значение (50% будет рисовать половину обводки прямоугольника).
Мне нужно сделать это в Javascript, так как я буду обновлять значение довольно часто.

<svg id="rectangle-timer" style="width:100%;height:100%;">
    <rect width="100%" height="100%"/>
</svg>

Я видел довольно хорошие библиотеки JS, такие как drawSVG или Vivus , но кажется, что они работают с путями, а не с базовыми формами, такими как прямоугольники.

Может кто-нибудь помочь?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Причина, по которой большинство библиотек будет использовать элементы path, заключается в том, что они наследуются от прототипа SVGGeometryElement, который предоставляет удобные функции для вычисления длины пути. Так что, если мы поменяем этот прямоугольник на путь вроде этого:

<path d="M 0 0 L 1 0 L 1 1 L 0 1 z" />

Мы получаем точно такой же вывод, но он гораздо более управляемый. После этого мы можем просто отрегулировать значение strokeDasharray в стиле, чтобы расширить и удалить некоторые штрихи. Для этого свойства нам просто нужны два значения: начальный размер тире и начальное пустое пространство. Поэтому, когда наш прогресс равен 0, мы хотим, чтобы первое значение равнялось 0, а второе - длине пути, а когда мы приближаемся к 1, мы хотим, чтобы второе значение равнялось 0, а первое значение увеличивалось до длины пути.

function update( amount ){
  
  const total = rect.getTotalLength();
  const filled = total * amount;
  const none = total - filled;
  
  rect.style.strokeDasharray = `${filled} ${none}`;
  
}

const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );

input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
    <path d="M 20 20 L 180 20 L 180 180 L 20 180 z" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>

<input id="input" type="range" min="0" max="1" step=".01" />

Если вы настаиваете на использовании rect, вы можете получить длину пути прямоугольника, взяв его ширину и высоту дважды, что будет выглядеть примерно так:

function update( amount ){
  
  const total = rect.width.baseVal.value * 2 + rect.height.baseVal.value * 2;
  const filled = total * amount;
  const none = total - filled;
  
  rect.style.strokeDasharray = `${filled} ${none}`;
  
}

const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );

input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
    <rect x="20" y="20" width="160" height="160" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>

<input id="input" type="range" min="0" max="1" step=".01" />

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

0 голосов
/ 21 января 2019

Это мое решение: SVG имеет preserveAspectRatio ="none" style="width:100%;height:100vh;" Общая длина пути равна 2*window.innerWidth + 2*window.innerHeight; И stroke-dasharray, и stroke-dashoffset равны общей длине пути.

I 'используя входной тип = "диапазон" для анимации stroke-dashoffset.Чтобы сохранить ширину хода и избежать растяжения, я использую vector-effect="non-scaling-stroke"

Надеюсь, это то, что вам нужно.

function timer(){
let totalLength = 2*window.innerWidth + 2*window.innerHeight;
thePath.setAttributeNS(null, "style", `stroke-dashoffset:${totalLength * (1-range.value)}`)
}
timer()

range.addEventListener("input",timer);


setTimeout(function() {
		timer()
		addEventListener('resize', timer, false);
}, 15);
*{margin:0; padding:0;}
#thePath {
  stroke-dasharray: calc(2 * 100vw + 2* 100vh);
  stroke-dashoffset: calc(2 * 100vw + 2* 100vh);
}
#rectangle-timer{background:#dfdfdf}
[type="range"] {
  position: absolute;
  display: block;
  width: 200px;
  height: 20px;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
<svg id="rectangle-timer" viewBox="0 0 100 100" preserveAspectRatio ="none" style="width:100%;height:100vh;">

    <path id="thePath" d="M0,0L100,0 100,100 0,100 0,0" fill="none" stroke="skyBlue" stroke-width="25" vector-effect="non-scaling-stroke" />
</svg>

<input type="range" id="range" value=".5" min="0" max="1" step=".01"  />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...