Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как в react-chartjs-2 задать отступ между круговой диаграммой и лейблами?

    @eminsk
    developer python, javascripts
    Самый простой способ - использовать layout.padding с динамическим вычислением отступов на основе количества и длины лейблов.
    const calculatePadding = (labels) => {
        const labelCount = labels.length;
        const maxLabelLength = Math.max(...labels.map(label => label.length));
        
        return {
            left: 40,
            right: Math.max(100, labelCount * 20 + maxLabelLength * 3)
        };
    };


    Более гибкое решение - отключить встроенную легенду и создать собственную
    <div className="pie-chart-grid-container">
        <div className="pie-chart-canvas">
            <Pie data={data} options={optionsWithoutLegend} />
        </div>
        <div className="custom-legend">
            {/* Кастомная легенда */}
        </div>
    </div>


    Убери фиксированные margin-left: 11% и используй flexbox или grid для центрирования:
    .pie-chart-wrapper {
        width: 100%;
        height: 100%;
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
    }


    Для мобильных устройств рекомендую размещать легенду снизу диаграммы вместо справа.
    Ответ написан
    Комментировать
  • Как обратится к значению proxy(object)?

    @eminsk
    developer python, javascripts
    Проблема в том, что filter() возвращает массив объектов, даже если найден только один элемент. В твоем случае test - это массив с одним объектом Proxy(Object), а не сам объект.
    Чтобы получить доступ к свойству hours, тебе нужно обратиться к первому (и единственному) элементу массива:
    const test = this.ArrBookingHours.filter((hour) => hour.date === day.toDateString())
    console.log(test)
    console.log(test[0].hours)

    строка console.log(test[0].hours) - это обращение к первому элементу массива

    Еще есть компактнее с использованием find и опциональной цепочки:
    const booking = this.ArrBookingHours.find(
      hour => hour.date === day.toDateString()
    )
    
    console.log(booking?.hours ?? 'Нет записи на эту дату')


    Используя этот способ - можно избежать ошибки Cannot read property 'hours' of undefined, если нет ни одного совпадения.
    Ответ написан
    Комментировать
  • Как сделать анимацию прорисовки линии в fabric 6?

    @eminsk
    developer python, javascripts
    Отключить кэширование объекта
    По умолчанию Fabric «кэширует» каждую фигуру в офф‑скрин канвасе для ускорения перерисовок. При анимации «динамических» свойств (как strokeDashOffset) кэш не всегда сбрасывается, поэтому ты не видишь промежуточных кадров. Решение — при создании линии сразу выключить objectCaching:
    function createLine(coords: [number, number, number, number]) {
      return new fabric.Line(coords, {
        stroke: '#000',
        strokeWidth: 2,
        originX: 'center',
        originY: 'center',
        // вот эта опция:
        objectCaching: false,
      });
    }


    Использовать requestRenderAll вместо renderAll
    Метод canvas.requestRenderAll() умнее: он при вызове внутри анимации сам батчит несколько обновлений в один кадр и гарантирует, что всё расчётное состояние Fabric будет учтено. А canvas.renderAll() может «проскочить» и отрисовать не все изменения.
    export function animateLineDraw(
      canvas: Canvas,
      line: Line,
      duration: number = 1000
    ) {
      const lineLength = Math.hypot(line.x2! - line.x1!, line.y2! - line.y1!);
    
      line.set({
        strokeDashArray: [lineLength, lineLength],
        strokeDashOffset: lineLength,
      });
    
      line.animate(
        { strokeDashOffset: 0 },
        {
          duration,
          easing: util.ease.easeInOutQuad,
          onChange: () => {
            console.log('onchange, strokeDashOffset:', line.strokeDashOffset);
            canvas.requestRenderAll();
          },
          onComplete: () => {
            console.log('oncomplete');
            line.set({
              strokeDashArray: undefined,
              strokeDashOffset: 0,
            });
            canvas.requestRenderAll();
          },
        }
      );
    }


    И убери вызов canvas.renderAll() сразу после animateLineDraw(...) — он не нужен, потому что первый кадр будет отрисован внутри onChange.
    Ответ написан