Рубрики
Без рубрики

Как создать компонент обратного отсчета, используя React & Momentjs

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

Автор оригинала: Florin Pop.

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

Вы можете найти окончательный результат в этом Пример кодепена :

Сначала мы создадим функциональность обратного отсчета, а затем мы посмотрим, как создать анимированную дугу, используя SVG с некоторыми модными функциями. ?

Создание функциональности обратного отсчета

Для этого мы собираемся использовать Импульс Библиотека, которая поможет нам Разбор, проверка, манипулировать, и Дисплей Даты и времена.

В основном то, что нам нужно, чтобы иметь 2 даты:

  • текущая дата или Теперь
  • последняя дата или тогда

Когда у нас есть эти 2 даты, мы можем вычесть сейчас от Тогда Использование момент И мы получим оставшееся время (или обратный отсчет ценность).

Для Тогда Дата, нам нужно пропустить 2 строки:

  • Один, TimeTilldate Строка, содержащая окончательную дату до которой мы хотим сосчитать (например, 05 26 2019, 6:00 утра )
  • два, TimeFormat Строка, которая используется момент Для проверки формата времени (в нашем примере было бы: Mm Dd Yyyy, H: MM A )

Вы можете узнать больше о разборных строках и форматировании их в Документация Отказ

Давайте посмотрим, как это выглядит в коде:

import moment from 'moment';

const then = moment(timeTillDate, timeFormat);
const now = moment();
const countdown = moment(then - now);

Примечание : TimeTilldate , TimeFormat Значения будут предоставлены внутри компонента реагирования. На данный момент мы используем их в качестве примеров.

От Обратный отсчет Объект Мы можем получить все значения, которые мы хотим отображать в нашем компоненте – дни , часы , минут и секунд осталось, пока мы не дойдем до Тогда время.

import moment from 'moment';

const then = moment(timeTillDate, timeFormat);
const now = moment();
const countdown = moment(then - now);
const days = countdown.format('D');
const hours = countdown.format('HH');
const minutes = countdown.format('mm');
const seconds = countdown.format('ss');

Позже мы добавим этот код в JS Интервал Это было бы назвать каждую секунду, но до того, как давайте настроим для него компонент реагирования.

Компонент обратного отсчета

Для этого мы собираемся создать Класс На основе компонента, так как нам нужен доступ к Государство компонента, потому что мы сохраним эти 4 значения ( дней , часы , минут , секунд ) в этом. По умолчанию эти значения являются undefined Отказ

import React from 'react';

class Countdown extends React.Component {
    state = {
        days: undefined,
        hours: undefined,
        minutes: undefined,
        seconds: undefined
    };

    render() {
        const { days, hours, minutes, seconds } = this.state;
      
        return (
            

Countdown

{days} days
{hours} hours
{minutes} minutes
{seconds} seconds
); } }

Далее давайте создадим Интервал который проходит каждую секунду и сохраняет значения в Государство компонента. Мы сделаем это Интервал внутри ComponentDidmount метод жизненного цикла. Мы собираемся в Чисто Интервал в ComponentWillunmount Способ жизненного цикла, поскольку мы не хотим, чтобы он не хочется работать после удаления компонента с DOM.

import React from 'react';
import moment from 'moment';

class Countdown extends React.Component {
    state = {
        days: undefined,
        hours: undefined,
        minutes: undefined,
        seconds: undefined
    };

    componentDidMount() {
        this.interval = setInterval(() => {
            const { timeTillDate, timeFormat } = this.props;
            const then = moment(timeTillDate, timeFormat);
            const now = moment();
            const countdown = moment(then - now);
            const days = countdown.format('D');
            const hours = countdown.format('HH');
            const minutes = countdown.format('mm');
            const seconds = countdown.format('ss');
            this.setState({ days, hours, minutes, seconds });
        }, 1000);
    }

    componentWillUnmount() {
        if (this.interval) {
            clearInterval(this.interval);
        }
    }

    render() {
        const { days, hours, minutes, seconds } = this.state;
      
        return (
            

Countdown

{days} days
{hours} hours
{minutes} minutes
{seconds} seconds
); } }

CSS.

У нас есть функциональность обратного отсчета все и работает сейчас, так что давайте стилься немного:

@import url('https://fonts.googleapis.com/css?family=Lato');

* {
    box-sizing: border-box;
}

body {
    font-family: 'Lato', sans-serif;
}

h1 {
    letter-spacing: 2px;
    text-align: center;
    text-transform: uppercase;
}

.countdown-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
}

.countdown-item {
    color: #111;
    font-size: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    line-height: 30px;
    margin: 10px;
    padding-top: 10px;
    position: relative;
    width: 100px;
    height: 100px;
}

.countdown-item span {
    color: #333;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
}

Ничто не нравится в CSS; Мы используем Flexbox Чтобы расположить предметы в обертке.

Наконец, давайте создадим SVG дуга, которая будет окружать каждый предмет в нашем обратном отсчете.

Компонент SVGCRCLE.

Прежде чем мы сделаем это, есть пара функций, которые нам нужно для создания настраиваемого SVG дуги Я нашел это на Stackoverflow Отказ Для получения дополнительной информации вы должны пойти туда и прочитать подробное объяснение функций.

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
    var angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0;
  
    return {
        x: centerX + radius * Math.cos(angleInRadians),
        y: centerY + radius * Math.sin(angleInRadians)
    };
}

function describeArc(x, y, radius, startAngle, endAngle) {
    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);
    var largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
    var d = [
        'M',
        start.x,
        start.y,
        'A',
        radius,
        radius,
        0,
        largeArcFlag,
        0,
        end.x,
        end.y
    ].join(' ');
  
    return d;
}

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

Вернуться к нашему компоненту React: мы собираемся создать SVG И у нас будет путь тег внутри этого, которая нарисует дугу ( D опоры), давая ему Радиус имущество. Другие 4 значения в Описания Функция фиксирована, так как мы не хотим их изменить, и мы настраиваем ее, чтобы хорошо выглядеть для нашего примера.

const SVGCircle = ({ radius }) => (
    
        
    
);

И нам также нужно немного CSS, чтобы позиционировать его внутри .countdown-item ( Посмотрите, где этот компонент идет в раздел окончательного результата):

.countdown-svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
}

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

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

function mapNumber(number, in_min, in_max, out_min, out_max) {
    return (
        ((number - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
    );
}

Окончательный результат

Наконец, давайте добавим новый Svgcircle Компонент внутри каждого из .countdown-item S и положить все вместе:

import React from 'react';
import moment from 'moment';

class Countdown extends React.Component {
    state = {
        days: undefined,
        hours: undefined,
        minutes: undefined,
        seconds: undefined
    };
    
    componentDidMount() {
        this.interval = setInterval(() => {
            const { timeTillDate, timeFormat } = this.props;
            const then = moment(timeTillDate, timeFormat);
            const now = moment();
            const countdown = moment(then - now);
            const days = countdown.format('D');
            const hours = countdown.format('HH');
            const minutes = countdown.format('mm');
            const seconds = countdown.format('ss');
            this.setState({ days, hours, minutes, seconds });
        }, 1000);
    }
    
    componentWillUnmount() {
        if (this.interval) {
            clearInterval(this.interval);
        }
    }
    
    render() {
        const { days, hours, minutes, seconds } = this.state;
        
        // Mapping the date values to radius values
        const daysRadius = mapNumber(days, 30, 0, 0, 360);
        const hoursRadius = mapNumber(hours, 24, 0, 0, 360);
        const minutesRadius = mapNumber(minutes, 60, 0, 0, 360);
        const secondsRadius = mapNumber(seconds, 60, 0, 0, 360);
        
        if (!seconds) {
            return null;
        }
        
        return (
            

Countdown

{days && (
{days} days
)} {hours && (
{hours} hours
)} {minutes && (
{minutes} minutes
)} {seconds && (
{seconds} seconds
)}
); } } const SVGCircle = ({ radius }) => ( ); // From StackOverflow: https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle function polarToCartesian(centerX, centerY, radius, angleInDegrees) { var angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0; return { x: centerX + radius * Math.cos(angleInRadians), y: centerY + radius * Math.sin(angleInRadians) }; } function describeArc(x, y, radius, startAngle, endAngle) { var start = polarToCartesian(x, y, radius, endAngle); var end = polarToCartesian(x, y, radius, startAngle); var largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1'; var d = [ 'M', start.x, start.y, 'A', radius, radius, 0, largeArcFlag, 0, end.x, end.y ].join(' '); return d; } // From StackOverflow: https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers function mapNumber(number, in_min, in_max, out_min, out_max) { return ( ((number - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min ); }

Все, что вам нужно сделать, чтобы использовать Обратный отсчет Компонент должен пройти через два реквизита ( TimeTilldate и TimeFormat Несомненно А ты золотой?

Заключение

Это был веселый маленький проект с реагированием, не так ли? ?

Когда я построил это, я узнал немного больше о том, как работать с Momentjs библиотека, а также с SVG с нарисовать дугу.

Дайте мне знать, если у вас есть какие-либо вопросы относительно этого учебника.

Счастливое кодирование! ?

Первоначально опубликовано www.florin-pop.com

Оригинал: “https://www.freecodecamp.org/news/how-to-create-a-countdown-component-using-react-momentjs-4717edc4ac3/”