Страницы

Поиск по вопросам

Показаны сообщения с ярлыком анимация. Показать все сообщения
Показаны сообщения с ярлыком анимация. Показать все сообщения

суббота, 11 апреля 2020 г.

Анимация в Android Canvas для minSdkVersion=“8”

#java #android #анимация #animate

                    
В моей словесной игре типа "Эрудита" для Android отсутствует анимация - 

Например, при выборе в меню "Вернуть буквы" фишки просто удаляются с игрового поля
и потом (вдруг!) показываются внизу экрана. 

Тоже самое с "Помешать буквы" - фишки просто рисуются на новых позициях внизу экрана:



Конечно, это выглядит не очень наглядно и мне хотелось бы добавить простые анимации
для буквенных фишек - но при этом не терять совместимость с Android 2.2 - поэтому нельзя
например использовать ValueAnimator.

Кроме того, мне кажется, что можно обойтись без Runnable и создания дополнительных
thread-ов - потому что я уже успешно анимирую flinging игрового поля (когда пользователь
скроллит его энергичным движением пальца) в главном thread при помощи ScrollerCompat.

Вот класс буквенных фишек:

public class Tile {
    public static int sWidth;
    public static int sHeight;

    // этот прямоугольник содержит координаты и размер фишки
    private Rect mRect = new Rect();


Для анимации я решил добавить в этот класс конечные координаты и флаг, что движение
фишки еще не закончилось:

    private Point mTarget = new Point();
    public boolean moving = false;


И два метода для перемещения фишки - без и с анимацией:

    public void move(int x, int y) {
        mRect.left = x;
        mRect.top = y;
        mRect.right = x + sWidth;
        mRect.bottom = y + sHeight;
    }

    public void moveAnimated(int x, int y) {
        moving = true;
        mTarget.x = x;
        mTarget.y = y;
    }


Потом, в методе отрисовки моего главного custom View я вызываю:

public class GameView extends View {
    private static final int DELAY = 30;
    private ArrayList mBarTiles = new ArrayList();

    @Override
    protected void onDraw(Canvas canvas) {
        if (mGameBoard.isFlinging()) {
            postInvalidateDelayed(DELAY);
        } else {
            for (SmallTile tile: mBoardTiles) {
                if (tile.moving) {
                    postInvalidateDelayed(DELAY);
                    break;
                }
            }
        }

        // нарисовать (с учетом scroll-а) игровое поле с фишками
        mGameBoard.draw(canvas, mBoardTiles);

        // нарисовать до 7 фишек внизу экрана - с анимацией
        for (SmallTile tile: mBarTiles) 
            tile.draw(canvas);

        // нарисовать 1 фишку которую тащит пользователь
        mDraggedTile.draw(canvas);
    }


Как видите наверху, если одна из фишек еще в процессе движения (и ее флаг moving=true),
то вызывается onDraw еще раз через 30 миллисекунд. 

То же самое для анимации игрового поля - если оно еще движется (isFlinging() возвращает
true) - но это уже работает без проблем.

Теперь собственно мой вопрос:

В процедуре отрисовке фишки нужно учесть ее движение и выставить ее актуальные координаты:

public void draw(Canvas canvas) {
    if (moving) {
        int dx = mTarget.x - mRect.left;
        int dy = mTarget.y - mRect.top;

        // ВОТ ЗДЕСЬ Я ЗАСТРЯЛ - КАКИЕ КООРДИНАТЫ ВЫСТАВИТЬ?
        move(XXX, YYY); 

        // ЕСЛИ ФИШКА ДОЛЕТЕЛА - НУЖНО ВЫСТАВИТЬ moving=false
    }

    // нарисовать background фишки - желтый прямоугольник
    canvas.drawRect(mRect, mPaint);

    // нарисовать Bitmap с буквой и ее числовым значением
    canvas.save();
    canvas.translate(mRect.left, mRect.top);
    Drawable d = sLetters.get(mLetter);
    d.draw(canvas);
    canvas.restore();
}


К сожалению, я не знаю как правильно подсчитать координаты!

У меня есть актуальные координаты фишки: mRect.left и mRect.top

У меня есть координаты куда должна прилететь фишка: mTarget.x и mTarget.y

Пока moving==true, каждые 30 миллисекунд вызывается код отрисовки фишки, которому
нужно дать новые координаты - но как их подсчитать?
    


Ответы

Ответ 1



Тогда вам нужно выбрать время анимации, допустим 1 секунда = 1000 миллисек. Тогда поделив 1000 на 30 (fps по сути) получаем 33 - количество раз, которое мы вызовем метод draw для достижения цели. Получается, что наш путь dx и dy тоже нужно поделить на 33, тогда мы получим шаг, на который у нас будет сдвигаться фишка, при каждом вызове draw. Ну а дальше остается прибавлять этот шаг к текущим координатам и с ними вызывать метод move: move(mRect.left + (int) (dx / 33), mRect.top + (int) (dy / 33));

понедельник, 30 марта 2020 г.

Как сделать чтобы анимация вызванная :hover продолжалась до конца, независимо от положения мыши?

#html #css3 #svg #анимация #svg_animation




body {
  margin: 0;
  padding: 0;
  background-color: #8e3a89;
  display: -webkit-flex;
  display: -moz-flex;
  display: -ms-flex;
  display: -o-flex;
  display: flex;
  justify-content: center;
  align-items: center;
}

.svg {
  margin: 10px;
  width: 150px;
  height: 150px;
}

.sas {
  fill: none;
  stroke: #fff;
  stroke-width: 3;
  stroke-dasharray: 2550;
}

.svg:hover .sas {
  animation: animate 3s;
}

@keyframes animate {
  0% {
    stroke-dashoffset: 2550;
  }
  100% {
    stroke-dashoffset: 0;
  }
}


Ответы

Ответ 1



body { margin: 0; padding: 0; background-color: #8e3a89; display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex; justify-content: center; align-items: center; } .svg { margin: 10px; width: 150px; height: 150px; border: 1px solid red; } .sas { fill: none; stroke: #fff; stroke-width: 3; stroke-dasharray: 2550; stroke-dashoffset: 0; }


Анимация градиента SVG под углом

#css #css3 #svg #анимация


Как правильно реализовать анимацию градиента SVG элемента под углом и с задержкой?



svg {
  transform: rotate(250deg);
}

    
    
      
        
      
      
        
      
    




    


Ответы

Ответ 1



Угол наклона градиента обеспечивают параметры: x1="45" x2="0" y1="75" y2="0" Анимация перехода градиента из одного цвета в другой: .crc1 ~ defs stop { transition: 3s; Подбирая значения цвета начального градиента -stop:first-child и конечного - stop:last-child можно получить очень интересные эффекты: Анимация начинается при наведении курсора: .crc1 { fill: url('#grad1'); } .crc1 ~ defs stop { transition: 3s; } .crc1 ~ defs stop:first-child { stop-color: #24bed2; } .crc1:hover ~ defs stop:last-child { stop-color: #F4FFAF; }

воскресенье, 29 марта 2020 г.

transition в canvas

#javascript #анимация #canvas #animate


Можно ли элементу в canvas добавить transition во время анимации? 






    
    Speedometer
    
    


Время загрузки 0.1 сек


Ответы

Ответ 1



CSS transition никак не применить к элементам на канве. Для получения плавной анимации в общем случае необходимо получать значения в зависимости от времени а не прибавлять каждый кадр фиксированные значения: Я изменил в Вашем примере одну функцию: let delay = 2; // задержка перед анимацией let duration = 3; // кол во секунд анимации роста значения let time = new Date().getTime(); // Время начала анимации let Engine = () => { // кол-во секунд с начала анимации let t = (new Date().getTime() - time) / 1000; val(+getValueFromTime(t).toFixed(1)); requestAnimFrame(Engine); }; // получить значение спидометра в зависимости от текущего времени function getValueFromTime(t) { if (t < delay) // если еще не прошло время задержки return 0 // вернем 0 t -= delay; // иначе вычитаем время задержки if (t < 0.95*duration) { // если прошло меньше 95 % времени анимации // переводим значение времени в значение при помощи функции сглаживания // EasingFunctions.easeOutCubic (значение на входе должно быть от 0 до 1) return 98 * EasingFunctions.easeOutCubic(t/duration); } // иначе это функция от синуса от этого значения return 98 + Math.sin(t * 55); } Функции сглаживания взяты отсюда, больше функций сглаживания тут
Время загрузки 0.1 сек


воскресенье, 8 марта 2020 г.

Создание анимации через потоки на Android

#java #android #многопоточность #canvas #анимация


Здравствуйте, стоит задача, на языке Java под ОС Android нужно написать задачу: создать
снеговика и сделать так, чтобы его составляющие объекты меняли цвет с разной скоростью.
Смена цветов должна быть реализована в потоке.
У меня получилось написать код, но не понимаю, как именно эта анимация должна в этот
поток помещаться. Вот собственно полный код, написан в Eclipse:

package ru.ucheba;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;

public class Zadanie2 extends Activity {
    int a = 255;
    int r = 100;
    int g = 0;
    int b = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new Panel(this));

    }

    class Panel extends View {
        public Panel(Context context) {
            super(context);
        }

        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint p1 = new Paint();
            p1.setStyle(Style.FILL);

            p1.setARGB(a, r, g, b);
            canvas.drawCircle(270, 170, 70, p1);
            for (int i = 0; i < 5; i++) {
                r--;
                SystemClock.sleep(10);
                invalidate();
            }

            for (int j = 0; j < 15; j++) {
                p1.setARGB(a, r, g, b);
                g--;
                canvas.drawCircle(270, 310, 100, p1);
                SystemClock.sleep(20);
                invalidate();
            }

            for (int k = 0; k < 30; k++) {
                p1.setARGB(a, r, g, b);
                b--;
                canvas.drawCircle(270, 510, 150, p1);
                SystemClock.sleep(40);
                invalidate();
            }
        }

        class Task extends Thread {
            @Override
            public void run() {

            }
        }
    }
}


Чем заполнять метод run() понимаю, но ругается либо на canvas, p1, или invalidate().
Прошу помощи
    


Ответы

Ответ 1



Ваш код принципиально неверен. В методе onDraw() нельзя вызывать sleep() и invalidate(). Это все вместе с изменением переменных argb должно происходить в отдельном потоке, а метод onDraw() только отрисовывать экран в соответствии с их состоянием. @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); p.setARGB(a, r1, g1, b1); canvas.drawCircle(270, 170, 70, p); p.setARGB(a, r2, g2, b2); canvas.drawCircle(270, 310, 100, p); p.setARGB(a, r3, g3, b3); canvas.drawCircle(270, 510, 150, p); } Перенести в конструктор и сделать переменной класса: p = new Paint(); p.setStyle(Style.FILL); В run() меняйте rX, gX, bX как вам надо и вызывайте синхронно с основным потоком invalidate() когда надо перерисовать.

Ответ 2



Выполнил вот таким образом, может кому-то поможет. Думаю, этот код можно написать гораздо лучше. Поэтому кто сможет, укажите на ошибки, буду благодарен. import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.view.View; public class Zadanie2 extends Activity { int[] Colo = { 10, 20, 30 }; // массив со значениями исп. для цветов // снеговика public Thread myThread1, myThread2, myThread3; // создание переменных для потоков @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new Panel(this)); // использование класса Panel в качестве активити myThread1 = new Thread(new Runnable() { @Override public void run() { int znak = 1; while (true) { if ((znak > 0) && (Colo[0] > 250)) { znak = -znak; } if ((znak < 0) && (Colo[0] < 5)) { znak = -znak; } Colo[0] += znak; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); myThread2 = new Thread(new Runnable() { @Override public void run() { int znak2 = 1; while (true) { if ((znak2 > 0) && (Colo[1] > 250)) { znak2 = -znak2; } if ((znak2 < 0) && (Colo[1] < 5)) { znak2 = -znak2; } Colo[1] += znak2; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); myThread3 = new Thread(new Runnable() { @Override public void run() { int znak3 = 1; while (true) { if ((znak3 > 0) && (Colo[2] > 250)) { znak3 = -znak3; } if ((znak3 < 0) && (Colo[2] < 5)) { znak3 = -znak3; } Colo[2] += znak3; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); // запуск потоков myThread1.start(); myThread2.start(); myThread3.start(); } class Panel extends View { public Panel(Context context) { super(context); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); float w, h, cx, cy, radius; // переменные, для адаптивного расположения снеговика w = getWidth(); // считывает ширину h = getHeight(); // считывает высоту cx = w / 2; cy = h / 2; // для ориентации экрана if (w > h) { radius = h / 8; } else { radius = w / 8; } Paint p1 = new Paint(); p1.setStyle(Paint.Style.FILL); p1.setColor(Color.rgb(Colo[0], 255, 255)); canvas.drawCircle(cx, cy - h / 3, radius, p1); Paint p2 = new Paint(); p2.setStyle(Paint.Style.FILL); p2.setColor(Color.rgb(255, Colo[1] * 2, 255)); canvas.drawCircle(cx, cy - h / 3 + radius * 2, (float) (radius * 1.5), p2); Paint p3 = new Paint(); p3.setStyle(Paint.Style.FILL); p3.setColor(Color.rgb(255, 255, Colo[2] * 3)); canvas.drawCircle(cx, cy - h / 3 + radius * 5, radius * 2, p3); invalidate(); // перерисовка объектов } } }

четверг, 5 марта 2020 г.

Как сделать анимацию SVG текста вокруг многоугольника

#css #анимация #svg


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

Конечно такие условия невозможно выполнить при большом количестве слов и размере
шрифта, но в определенных рамках это возможно? 

Например, чтобы такие разные фразы, как:


Текст шестиугольника
Текст вокруг шестиугольника 
Весь текст целиком вокруг шестиугольника


Одинаково равномерно размещались вокруг сторон шестиугольника без перекрытия начала
и конца фразы.  

Далее, необходимо сделать анимацию текста вокруг шестиугольника. 










    


Ответы

Ответ 1



Чтобы разместить текст целиком вокруг фигуры необходимо узнать длину пути, то есть длину периметра сторон многоугольника. Для нашего примера длина периметра многоугольника будет равна 760px Чтобы конец текстовой фразы не перекрывал символы начала и был гарантированный промежуток между ними,- установим textLength="700" Теперь для текста применим атрибут lengthAdjust="spacingAndGlyphs", который выполняет согласование между установленной длиной textLength="700" и расчетной длиной текстовой фразы, которая может иметь различные длины в зависимости от количества слов и размера шрифта. Другими словами она уплотняет текстовую фразу до заданных размеров textLength="700" за счет уменьшения ширины отдельных символов Анимация текста вдоль сторон многоугольника достигается изменением атрибута attributeName="startOffset" Ниже пример, который работает и в Chrome, FireFox, Opera, IE11 (кроме анимации) Начало анимации - клик на кнопке "Старт" Весь очень длинный текст целиком вокруг шестиугольника Старт

Синхронизировать канвас с анимацией

#javascript #css3 #анимация #canvas #css_animation


В каждом фрейме отрисовки (requestAnimationFrame) в центре канваса рисуется круг.
Размер канваса анимируется. В Хроме и FF круг немного дрожит, а в IE он заметно толстеет
перед перерисовкой - т. е. браузер сначала растягивает имеющуюся картинку, а потом
заменяет её новой. Почему так происходит и как исправить?



Насколько я представляю, если я делаю что-то в requestAnimationFrame, то содержимое
страницы вообще не должно перерисовываться, пока я не закончу. Соответственно, на момент
отрисовки должна отрисоваться сразу новая версия. Но в IE сценарий не такой?

https://jsfiddle.net/3wLroppt/



function draw() {
  var canvas = document.querySelector('canvas');
  
  var width = canvas.clientWidth, height = canvas.clientHeight;
  
  canvas.width = width * 2;
  canvas.height = height * 2;
  
  var ctx = canvas.getContext('2d');
  
  var cx = width, cy = height, r = height;
  
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, 2 * Math.PI, false);
  ctx.fill();
}

requestAnimationFrame(function frame() {
  draw();
  requestAnimationFrame(frame);
});
canvas {
  outline: 1px dotted red;
  height: 200px;
  width: 200px;
  display: block;
  margin: auto;
  animation: w-100-200 .5s linear infinite;
}

@keyframes w-100-200 {
    0% { width: 200px; }
   50% { width: 400px; }
  100% { width: 200px; }
}




    


Ответы

Ответ 1



Нашел ответ, правда на IE пока не тестировал, у меня linux))) Как я и подозревал дело было в том что анимация с высотой и шириной по умолчанию происходит так: Например у вас ширина должна с 200px расшириться до 400px в определенном промежутке времени ($t), и расчет происходит так - к ширине добавляется один пиксель в (400-200) / $t времени.И кода размер ширины контейнера нечетное количество пикселей то центр круга рисуется на один пиксель вправо (по оси x) (201/2 пиксель шириной для него будет 101px), и это приводит к непредусмотренной анимации (дрожанию) круга внутри контейнера. Эту проблему я решил свойством animation-timing-function, у него есть значение steps. там можно задать шаг анимации и у нас поскольку от 200 - 400 будет 100 2-пиксельных шагов прописываем в нем 100 animation-timing-function: steps(100); И вот что у меня получилось: А это пример от автора но время я поставил 5s что бы наглядно было видно непредусмотренная анимация черного круга.

Ответ 2



Вы же сами написали - браузер сначала рисует кружок с помощью js,а css его тем временем растягивает. let start = Date.now(); const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const height = canvas.clientHeight; function draw() { let dt = Date.now() - start; var side = Math.pow(-1, ~~(dt/500)); var delta_width = 200 * (dt%500)/500; width = canvas.width = ((side>0)?200:400) + side * delta_width; prev = Date.now(); var cx = width/2, cy = height, r = height; ctx.beginPath(); ctx.arc(cx, 100, 100, 0, 2 * Math.PI, false); ctx.fill(); } setInterval(draw, 54); canvas { outline: 1px dotted red; height: 200px; display: block; margin: auto; }

воскресенье, 1 марта 2020 г.

Как добавить ссылку внутри круга SVG

#javascript #html #css #svg #анимация


Я нарисовал круг, используя svg. Этот круг имеет эффект :hover.
Я хотел бы добавить ссылку внутри круга и для текста ссылки изменить цвет при наведении
курсора. 

Ниже мой код:   



svg#circle {
  height: 250px;
  width: 250px;
}

circle {
  stroke-dasharray: 700;
  stroke-dashoffset: 700;
  stroke-linecap: butt;
  -webkit-transition: all 2s ease-out;
  -moz-transition: all 2s ease-out;
  -ms-transition: all 2s ease-out;
  -o-transition: all 2s ease-out;
  transition: all 2s ease-out;
}

circle:hover {
  fill: pink;
  stroke-dashoffset: 0;
  stroke-dasharray: 700;
  stroke-width: 10;
}

    
 



    


Ответы

Ответ 1



Вам нужно добавить элемент, завернутый в ссылку . Обратите внимание, что элемент, находящийся поверх круга, заблокирует действие наведения на тексте в круге. Поэтому я обернул все это в группу и сделал :hover на группу. svg#circle { height: 250px; width: 250px; } g circle { stroke-dasharray: 700; stroke-dashoffset: 700; stroke-linecap: butt; -webkit-transition: all 2s ease-out; -moz-transition: all 2s ease-out; -ms-transition: all 2s ease-out; -o-transition: all 2s ease-out; transition: all 2s ease-out; } g:hover circle { fill: pink; stroke-dashoffset: 0; stroke-dasharray: 700; stroke-width: 10; } text { fill: pink; font-size: 24px; } a:hover text { fill: blue; } google Источник: How to add a link inside an svg circle @Paulie_D

Ответ 2



Ответ с динамическим добавлением ссылки Я думаю, что это сработает: Динамическое добавление ссылки на SVG Circle с помощью JS function addAnchor(){ var dummyElement = document.createElement("div"); dummyElement.innerHTML = '
'; var htmlAnchorElement = dummyElement.querySelector("a"); var circleSVG = document.getElementById("circle"); htmlAnchorElement.innerHTML = circleSVG.innerHTML; circleSVG.innerHTML = dummyElement.innerHTML; } Источник: How to add a link inside an svg circle @Jyothi Babu Araja

пятница, 28 февраля 2020 г.

css animations, которые внезапно завершаются сбоем вне ui

#html #css #css3 #анимация



Вопрос: может ли css определить, если анимация незавершена? 

 

storytime: У меня классный ui с анимированными кнопками. Они расширяются при наведении,
поэтому другие кнопки на панели  должны одновременно сжиматься. 

 

Моя проблема (характерная не только для этого примера, но также и общая, потому что
у меня были такие же проблемы и в других случаях). Когда я быстро перехожу по всем
кнопкам, чтобы ускорить 2 кнопки, они сокращаются, и только одна кнопка растет, и поэтому
они не заполняются как они должны,-  справа появляется белая полоска.  

код с ошибкой:  

.container:hover button{
    width: calc((100% / 3) - 5%);
}
.container button:hover{
    width: calc((100% / 3) + 10%);
}  


Полный код:  



.container {
  width: 375px;
  height: 100px;
}

.container button {
  transition: .15s;
  float: left;
  height: 100%;
  border: none;
  object-fit: cover;
  width: calc(100% / 3);
}

.container:hover button {
  width: calc((100% / 3) - 5%);
}

.container button:hover {
  width: calc((100% / 3) + 10%);
}

button.green {
  background-color: #27ae60;
  color: white;
}

button.blue {
  background-color: #3498db;
  color: white;
}

button.white {
  background-color: #ecf0f1;
}

body {
  background-color: #929AAA;
}

div.container {
  background-color: #FFF;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  margin: calc(100vh / 4 - 50px) auto
}
Ещё один пример - Codepen


Ответы

Ответ 1



Идея состоит в том, чтобы сделать только один элемент, с увеличением размера при наведении, а другие при этом должны уменьшится. Вот пример с flexbox: .container { width: 375px; height: 100px; display: flex; } button { transition: .15s; flex: 1; border: none; } /* you want to have 28% + 44% + 28% so it's 1 + 1.57 + 1*/ .container button:hover { flex: 1.57; } /*For styling*/ button.green { background-color: #27ae60; color: white; } button.blue { background-color: #3498db; color: white; } button.white { background-color: #ecf0f1; } body { background-color: #929AAA; } div.container { background-color: #FFF; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); margin: calc((100vh - 100px) / 2) auto }


четверг, 27 февраля 2020 г.

Как переместить только одну точку из множества в SVG?

#javascript #html #css #svg #анимация


Пишу SVG + анимация, и столкнулся с такой задачей,-  нужно анимировать только одну
точку из множества в координатах SVG(чтобы эта точка плавно изменяла свое местоположение
с привязкой линии от других точек).
Например: 

d="M10,10 L20,10 L20,20 z" //чтобы плавно переместилась в
d="M10,10 L123,10 L20,20 z"


Как это можно сделать только кодом? Без сторонних программ типа Иллюстратора
    


Ответы

Ответ 1



Анимируется атрибут d патча. Подставляется первое значение и финальное положение, через точку с запятой values="M10,10 L20,10 L20,20 z;M10,10 L123,10 L20,20z;M10,10 L20,10 L20,20 z" .container { width:100%; height:100%; }
Туда, обратно Подставляется в values три значения: стартовое;финальное;стартовое .container { width:100%; height:100%; }
В атрибут values можно подставить сколько угодно промежуточных значений патча, главное следить, чтобы количество контрольных точек было одинаково у всех промежуточных значений

CSS - Как размыть маску SVG?

#css #html5 #svg #анимация #clip_path


Я пытался размыть SVG clip-path.
 Пробовал разные решения, но ни одно не помогло.  

Я не уверен, есть ли другое решение, кроме фильтра.

Pseudocode  


SVG clip-path должен раскрывать текст ниже  
Края, если SVG clip-path применен должны быть размытыми  


HTML



    .wrapper {
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
    }
    
    .h1, blur {
      width: 100vw;
      height: 100vh;
    }
    
    .h1 {
      position: absolute;
      top: 0;
      left: 0;
      margin: 0;
      padding: 0;
      font-size: 4em;
      clip-path: url(#svgPath);
      background-color: blue;
    }
    
    .blur {
      position: absolute;
      top: 0;
      left: 0;
      margin: 0;
      padding: 0;
      font-size: 4em;
      color: blue;
      background-color: white;
      filter: blur(8px)
    }

Our principles inform everything we do. Whether you're preparing content, designing an interface or developing an entire service, start by reading these.

Our principles inform everything we do. Whether you're preparing content, designing an interface or developing an entire service, start by reading these.


Ответы

Ответ 1



Хорошо, вот способ сделать это, используя radial-gradient() в качестве mask-image. var h1 = document.getElementById('masked'); document.addEventListener('mousemove', mouseListen, false); function mouseListen(e){ setMaskPos(e.clientX,e.clientY); } function setMaskPos(x,y) { h1.setAttribute("style", "-webkit-mask-image: radial-gradient(circle at " + x + "px " + y + "px, black 0px, black 200px, transparent 250px)"); } // Initialise the mask off screen setMaskPos(-999,0); .wrapper { display: flex; justify-content: center; align-items: center; position: relative; } .h1, blur { width: 100vw; height: 100vh; } .h1 { position: absolute; top: 0; left: 0; margin: 0; padding: 0; font-size: 4em; background-color: white; } .blur { position: absolute; top: 0; left: 0; margin: 0; padding: 0; font-size: 4em; background-color: white; filter: blur(8px) }

Our principles inform everything we do. Whether you're preparing content, designing an interface or developing an entire service, start by reading these.

Our principles inform everything we do. Whether you're preparing content, designing an interface or developing an entire service, start by reading these.



среда, 26 февраля 2020 г.

Асинхронное движение изображений в js (canvas)

#javascript #анимация #canvas


Предположим имеется 1 изображение машины. Необходимо создать два объекта Image с
этой машиной и двигать эти два изображения асинхронно. Привожу код, работает он явно
не так как нужно, по задумке - вторая машина должна изначально отставать от первой
и обе должны двигать влево с какой-то скоростью. В итоге получается слияние двух машин,
будто это не два разных объекта, а один.

Наработки: https://jsfiddle.net/o236kta5/2/









    
    






    


Ответы

Ответ 1



Залог плавной анимации - функция положения объектов от времени между кадрами setInterval это плохо, но срабатывает через фиксированные интервалы времени, для вызова отрисовки в современных браузерах есть специальный метод -requestAnimationFrame, браузер сам вызывает функцию переданную в этот метод, когда соберется отрисовать следующий кадр, на разных платформах это работает по-разному, например на мобильных устройствах он вызывается реже для экономии электроэнергии, так же он реже вызывается для неактивных вкладок. let t = 0 let c = canvas.getContext('2d'); let cars = Array(7).fill(0).map((e,i) => ({ x: 560, y: i*20, v: 0.2 + Math.random()/3 })); function draw(dt) { // dt время с начала анимации c.clearRect(0, 0, canvas.width, canvas.height); cars.forEach(car => { car.x -= (dt-t)*car.v; car.x = car.x < 0 ? 600 : car.x; c.drawImage(img, car.x , car.y, img.width, img.height); }); t = dt; requestAnimationFrame(draw); }

вторник, 25 февраля 2020 г.

Линейное движение точки под углом: отскок

#анимация #алгоритм #геометрия


Приветствую.
В общих чертах, пишу алгоритм перемещения точки в пределах прямоугольника, скажем
600 x 400. Точка имеет такие свойства:

текущие координаты X и Y, при чем, X = [0,600]; Y = [0,400] (просто перемещаю div
по relative-контейнеру)
кинетический заряд A (длина шага за 1 такт — гипотенуза)
угол Angle (град.)

Сначала долго ломал голову насчет самого передвижения точки в направлении, указанном
углом Angle. Когда обнаружил решение, стало стыдно. Вот оно:
X = X + A * cos(Angle * PI / 180);
Y = Y + A * sin(Angle * PI / 180);

С этим все нормально:

если Angle = 0, то точка движется вправо по OX,
если Angle = 180, то влево,
если Angle = 90, то вниз по OY (!),
если 45 — то вправо-вниз...

Но уже битый час не могу понять, какие ставить условия и как разворачивать угол при
столкновении со «стеной» прямоугольника, которым описана площадь, за которую точка
не должна вылезти.
В каждой итерации (такт) происходит смещение точки по приведенным выше формулам и
делается тест на столкновение. Извиняюсь за толстую просьбу, но я прошу дополнить (поправить?)
эту секцию кода:
if (x <= 0)
    { Angle = ... }
else if (x >= 600)
    { Angle = ... }

if (y <= 0)
    { Angle = ... }
else if (y >= 400)
    { Angle = ... }

И еще у меня может быть и само движение неправильно описано, тоже поправьте пожалуйста,
если так (у меня такое впечатление, что по-правильному, с увеличением угла Angle траектория
точки должна заворачиваться против, а не по часовой — как у меня).    


Ответы

Ответ 1



исправил я функцию step, обратите внимания на коментарии this.step = function() { this.x = this.x + this.a * Math.cos(this.angle * Math.PI / 180); this.y = this.y + this.a * Math.sin(this.angle * Math.PI / 180); if (this.x <= 0) { // this.angle = 180 - this.angle; if (this.angle < 0) this.angle += 360; // что бы угол был положительным } else if (this.x >= 600) { // 0 -> 180 10 -> 170 this.angle = 180 - this.angle; if (this.angle < 0) this.angle += 360; } if (this.y <= 0) { // 270 -> 90 269 -> 91 this.angle = 360 - this.angle; } else if (this.y >= 400) { // 90 -> 279 180 - 180 this.angle = 360 - this.angle; } return this; }; или даже ещё короче this.step = function() { this.x = this.x + this.a * Math.cos(this.angle * Math.PI / 180); this.y = this.y + this.a * Math.sin(this.angle * Math.PI / 180); if (this.x <= 0 | this.x >= 600) { // this.angle = 180 - this.angle; if (this.angle < 0) this.angle += 360; } if (this.y <= 0 | this.y >= 400) { // 270 -> 90 269 -> 91 this.angle = 360 - this.angle; } return this; };

Почему не работает transition у высоты, заданной в процентах?

#html #css #css3 #анимация #transition


Почему пропадет transition при указании % соотношения?

код

.buttom:hover ~ .container{
    /*height:500px;*/
    height: 100%;
}


Если указать height: 500px работает плавный переход, если указать height: 100% раскрытие
проходит мгновенно.

Подскажите почему и как правильно изменить код. 
    


Ответы

Ответ 1



В твоём коде 100% на самом деле означают auto, поскольку у контейнера не задана высота. Если её задать, то плавное разворачивание будет. html, body { height: 100%; } http://jsfiddle.net/m8oc7knn/1/

Ответ 2



Понял, как сделать, чтобы transition заработал без указания высоты. Пусть высота всегда будет auto, а изменяется максимальная высота: .container{ max-height: 50px; } .buttom:hover ~ .container{ max-height: 1000px; } http://jsfiddle.net/m8oc7knn/2/ Хотя это не совсем так работает, как надо. Анимируется весь диапазон max-height, а не высота.

Ответ 3



Свойство height относится к свойствам, которые лучше не анимировать, потому что анимировать желательно всего два свойства — opacity и transform. При анимации height браузер начинает перерасчитывать макет, а значит на каждом фрейме анимации будет вызвана перерисовка. Чтобы этого избежать, в нашем случае, будем анимировать transform. Для начала, необходимо вынести объект, который будем анимировать, в отдельный композиционный слой — это делается при помощи will-change: transform или по-старинке transform: translateZ(0). А после этого уже можно воспользоваться трюком с transform: scaleY(0) / scaleY(1). Самостоятельно разницу можно пощупать в Developer Tools → Console → esc → Rendering → Paint Flashing. div { position: relative; display: inline-block; } menu { position: absolute; top: 100%; will-change: transform; transition: transform .3s; transform: scaleY(0); transform-origin: 50% 0; background: #fff; border: 1px solid #ccc; padding: 10px 0; margin: 0; } menu ul { padding: 0; margin: 0; list-style-type: none; } menu a { display: block; padding: 5px 15px; text-decoration: none; color: #000; } menu a:hover { background: #000; color: #fff; } span { padding: 5px 10px; border: 1px solid #ccc; display: inline-block; cursor: default; } div:hover > menu { transform: scaleY(1); }

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, ratione error, hic alias officiis voluptatibus ipsa natus ab maxime accusamus rerum sunt aliquid. Ratione vero blanditiis assumenda, nisi non. A.



понедельник, 24 февраля 2020 г.

Как держать два объекта на постоянном расстоянии друг от друга?

#javascript #алгоритм #анимация


Здравствуйте! Такая задача: есть две точки, они должны держаться на постоянном расстоянии
друг от друга. Если начинаешь двигать за одну точку, то другая идет следом за ней,
как бы два конца одной палки.





Как это можно реализовать? В одной книге про анимации была написана следующая реализация:

function springTo(pointA, pointB) {
    var dx = pointB.x - pointA.x,
        dy = pointB.y - pointA.y,
        angle = Math.atan2(dy, dx),
        targetX = pointB.x - Math.cos(angle) * 100,
        targetY = pointB.y - Math.sin(angle) * 100;

    pointA.vx += (targetX - pointA.x) * pointA.spring;
    pointA.vy += (targetY - pointA.y) * pointA.spring;
    pointA.vx *= pointA.friction;
    pointA.vy *= pointA.friction;
    pointA.x += pointA.vx;
    pointA.y += pointA.vy;
}


Код написан на JS. Что делает этот код: в функцию передаются два значения (точка
А и точка Б). В той части, где происходит инициализация переменных происходит подсчет
конечного положения точки А, то есть того положения куда нужно сдвинуть точку, чтобы
расстояние между точками было равным 100. Собственно потом мы точку А двигаем в нужном
направлении. Чем плох этот способ для меня: точки двигаются плавно. Мне же нужно чтобы
они двигались ровно, как палка.

Вот пример https://jsfiddle.net/0b1whd87/1/ , чтобы было понятнее. 
    


Ответы

Ответ 1



Пример решения: https://jsfiddle.net/gambala/urzmyv5x/ Алгоритм: Головная точка (за которую цепляем) мгновенно перемещается туда, где курсор; Хвостовая точка (другая из двух) встает так, чтобы расстояние между ей и головной не изменилось (было 50px, осталось 50px, без пружинивания). Для этого хвостовая точка: Поворачивается туда, куда перемещается головная точка; Делает столько шагов вперед (или назад), чтобы в итоге расстояние от нее до головной точки было таким же, как и всегда. Это делает функция updateTailPoint: function updateTailPoint(tailPoint, handlePoint) { var dx = handlePoint.x - tailPoint.x, dy = handlePoint.y - tailPoint.y, angle = Math.atan2(dy, dx), distance = Math.sqrt(dx*dx + dy*dy); tailPoint.x += (distance - 50) * Math.cos(angle); tailPoint.y += (distance - 50) * Math.sin(angle); } Где 50 - это "эталонное" расстояние между точками, которое хвостовая точка беспрекословно соблюдает.

воскресенье, 23 февраля 2020 г.

Масштабируемая сетка из шестигранников

#css #html5 #css3 #анимация #svg


Я загрузил из Интернета  несколько изображений на мой сайт . Можно ли придать всем
этим образам  шестигранную форму в responsive grid?    

... Я нашел несколько способов сделать это, но мне необходимо заполнить src изображения в коде CSS. Это не подходит мне, потому что сайт загружает случайные изображения из интернета с jQuery, поэтому я не могу их использовать как фоновые изображения. Я собираюсь поддерживать WebKit браузеры, Firefox, IE8 было бы хорошо, но не нужно - и мобильные браузеры Моя попытка здесь: jsfiddle перевод вопроса: Responsive grid of hexagons


Ответы

Ответ 1



Здесь demo и репозиторий для responsive grid of hexagons. Код здесь не поддерживается. Он был перемещен в GitHub и сильно улучшены комментарии, вопрос отчетности и взносы должны быть сделаны туда. Этот метод использует: тег неупорядоченный список: каждый шестиугольник содержится в теге
  • и теге Использование transform rotateи skew, чтобы сделать шестигранные формы overflow:hidden; дочерние элементы nth-child() заполняют шестигранник в качестве pattern И еще, чтобы создать шестигранную сетку с тегом . Характеристики шестигранной сетки : Сетка будет реагировать, как это полагается, на изменение процентов ширины. Шестиугольники поддерживают своё соотношение сторон в соответствии с приемом padding-bottom technique и изображения изменяют размер, чтобы соответствовать форме шестиугольника. hover эффект поверх шестиугольников: текст скользит с прозрачным наложением над изображением. Каждый шестиугольник сохраняет свои границы: эффект hover (или событие click ) для каждого шестиугольника срабатывает только внутри реальной фигуры. Полный код Следующий фрагмент кода не является последней версией сетки. GitHub repo сохраняется и до настоящего времени. Вопросы и вклады могут быть сделаны там. * { margin: 0; padding: 0; } body { font-family: 'Open Sans', arial, sans-serif; background: rgb(123, 158, 158); } #hexGrid { overflow: hidden; width: 90%; margin: 0 auto; padding:0.707% 0; } #hexGrid:after { content: ""; display: block; clear: both; } .hex { position: relative; list-style-type: none; float: left; overflow: hidden; visibility: hidden; -webkit-transform: rotate(-60deg) skewY(30deg); -ms-transform: rotate(-60deg) skewY(30deg); transform: rotate(-60deg) skewY(30deg); } .hex * { position: absolute; visibility: visible; } .hexIn { display:block; width: 100%; height: 100%; text-align: center; color: #fff; overflow: hidden; -webkit-transform: skewY(-30deg) rotate(60deg); -ms-transform: skewY(-30deg) rotate(60deg); transform: skewY(-30deg) rotate(60deg); -webkit-backface-visibility: hidden; backface-visibility: hidden; } /* HEX CONTENT */ .hex img { left: -100%; right: -100%; width: auto; height: 100%; margin: 0 auto; } .hex h1, .hex p { width: 90%; padding: 0 5%; background-color: #008080; background-color: rgba(0, 128, 128, 0.8); font-family: 'Raleway', sans-serif; -webkit-transition: top .2s ease-out, bottom .2s ease-out, .2s padding .2s ease-out; transition: top .2s ease-out, bottom .2s ease-out, .2s padding .2s ease-out; } .hex h1 { bottom: 110%; font-style: italic; font-weight: normal; font-size: 1.5em; padding-top: 100%; padding-bottom: 100%; } .hex h1:after { content: ''; display: block; position: absolute; bottom: -1px; left: 45%; width: 10%; text-align: center; z-index: 1; border-bottom: 2px solid #fff; } .hex p { padding-top: 50%; top: 110%; padding-bottom: 50%; } /* HOVER EFFECT */ .hexIn:hover h1 { bottom: 50%; padding-bottom: 10%; } .hexIn:hover p { top: 50%; padding-top: 10%; } /* SPACING AND SIZING */ @media (min-width:1201px) { .hex { width: 19.2%; /* = (100-4) / 5 */ padding-bottom: 22.170%; /* = width / sin(60deg) */ } .hex:nth-child(9n+6), .hex:nth-child(9n+7), .hex:nth-child(9n+8), .hex:nth-child(9n+9) { margin-top: -4.676%; margin-bottom: -4.676%; -webkit-transform: translateX(50%) rotate(-60deg) skewY(30deg); -ms-transform: translateX(50%) rotate(-60deg) skewY(30deg); transform: translateX(50%) rotate(-60deg) skewY(30deg); } .hex:nth-child(9n+6):last-child, .hex:nth-child(9n+7):last-child, .hex:nth-child(9n+8):last-child, .hex:nth-child(9n+9):last-child { margin-bottom: 0; } .hex:nth-child(9n+6) { margin-left: 0.5%; clear: left; } .hex:nth-child(9n+10) { clear: left; } .hex:nth-child(9n+2), .hex:nth-child(9n+ 7) { margin-left: 1%; margin-right: 1%; } .hex:nth-child(9n+3), .hex:nth-child(9n+4), .hex:nth-child(9n+8) { margin-right: 1%; } } @media (max-width: 1200px) and (min-width:901px) { .hex { width: 24.25%; /* = (100-3) / 4 */ padding-bottom: 28.001%; /* = width / sin(60deg) */ } .hex:nth-child(7n+5), .hex:nth-child(7n+6), .hex:nth-child(7n+7) { margin-top: -6.134%; margin-bottom: -6.134%; -webkit-transform: translateX(50%) rotate(-60deg) skewY(30deg); -ms-transform: translateX(50%) rotate(-60deg) skewY(30deg); transform: translateX(50%) rotate(-60deg) skewY(30deg); } .hex:nth-child(7n+5):last-child, .hex:nth-child(7n+6):last-child, .hex:nth-child(7n+7):last-child { margin-bottom: 0; } .hex:nth-child(7n+2), .hex:nth-child(7n+6) { margin-left: 1%; margin-right: 1%; } .hex:nth-child(7n+3) { margin-right: 1%; } .hex:nth-child(7n+8) { clear: left; } .hex:nth-child(7n+5) { clear: left; margin-left: 0.5%; } } @media (max-width: 900px) and (min-width:601px) { .hex { width: 32.666%; /* = (100-2) / 3 */ padding-bottom: 37.720%; /* = width / sin(60) */ } .hex:nth-child(5n+4), .hex:nth-child(5n+5) { margin-top: -8.564%; margin-bottom: -8.564%; -webkit-transform: translateX(50%) rotate(-60deg) skewY(30deg); -ms-transform: translateX(50%) rotate(-60deg) skewY(30deg); transform: translateX(50%) rotate(-60deg) skewY(30deg); } .hex:nth-child(5n+4):last-child, .hex:nth-child(5n+5):last-child { margin-bottom: 0; } .hex:nth-child(5n+4) { margin-right: 1%; margin-left: 0.5%; } .hex:nth-child(5n+2) { margin-left: 1%; margin-right: 1%; } .hex:nth-child(5n+6) { clear: left; } } @media (max-width: 600px) { .hex { width: 49.5%; /* = (100-1) / 2 */ padding-bottom: 57.158%; /* = width / sin(60) */ } .hex:nth-child(3n+3) { margin-top: -13.423%; margin-bottom: -13.423%; -webkit-transform: translateX(50%) rotate(-60deg) skewY(30deg); -ms-transform: translateX(50%) rotate(-60deg) skewY(30deg); transform: translateX(50%) rotate(-60deg) skewY(30deg); } .hex:nth-child(3n+3):last-child { margin-bottom: 0; } .hex:nth-child(3n+3) { margin-left: 0.5%; } .hex:nth-child(3n+2) { margin-left: 1%; } .hex:nth-child(3n+4) { clear: left; } } Изменение количества шестиугольников в ряду Сетка адаптирует количество шестиугольников в ряду в зависимости от ширины окна просмотра. С пятью шестиугольниками на экранах шире, чем 1200px, и до 2-х на экранах уже, чем 600px. Если вам не нужны media queries, но просто хотите изменить количество шестиугольников в строке, то вы можете сохранить CSS из соответствующего media queries и затем удалить ненужные из них. Для получения дополнительных настроек см. sizing and spacing of hexagons. Demos Для получения списка всех демок, посмотрите эту коллекцию на codepen: Responsive grids of hexagons с разным числом шестиугольников в каждом ряду, а также опции центрирования и многое другое ... Вот оригинал codepen demo с .pusher элементом, чтобы сделать неправильную сетку из шестиугольников. .pusher элемент используется для создания "дыр" в сетке с пустыми шестиугольниками. Перевод ответа: @web-tiki