Squeak.ru - шаблоны программирования

Использование d3.js svg clipPath не обрезается в Angular

Я разрабатываю график, очень похожий на следующий пример: http://bl.ocks.org/mbostock/1667367, где он использует clipPath для обрезки области, чтобы график области не переполнял ось.

Используя тот же пример в директиве Angular, он работает почти все правильно, кроме отсечения. При использовании функции фокусировки линия графика выходит за пределы прямоугольника отсечения.

Но тот же код в jsFiddle работает правильно http://jsfiddle.net/gserra/TXYGH/. Упомянутый код в Директиве следующий:

angular.module('casApp.directives', []).
  directive('lineChart', ['d3', '_', 'moment', function (d3, _, moment) {
    var margin = {top: 10, right: 10, bottom: 100, left: 40};
    var margin2 = {top: 430, right: 10, bottom: 20, left: 40};

    return {
      restrict: 'E',
      replace: true,
      scope: {
        data: '=',
        stream: '=',
        start: '=',
        end: '=',
        period: '@',
        unit: '@',
        sensor: '@',
        width: '@',
        height: '@'
      },
      template: '<div class="line-chart"></div>',
      controller:'DataCtrl',
      link: function (scope, element) {
        var height = scope.height - margin.top - margin.bottom,
          height2 = scope.height - margin2.top - margin2.bottom,
          width = scope.width - margin.left - margin.right;

        scope.updateTime();

        var x = d3.time.scale()
          .domain([scope.start, scope.end])
          .range([0, width]);

        var x2 = d3.time.scale()
          .domain(x.domain())
          .range([0, width]);

        var min = d3.min(scope.data, function (d) {return d.value; })
        var max = d3.max(scope.data, function (d) {return d.value; })
        var thres = Math.abs(max-min);

        var y = d3.scale.linear()
          .domain([min - thres, max + thres])
          .range([height, 0]);

        var y2 = d3.scale.linear()
          .domain(y.domain())
          .range([height2, 0]);

        var line = d3.svg.line()
          .x(function (d) {
            return x(moment(d.at));
          })
          .y(function (d) {
            return y(d.value);
          });

        var line2 = d3.svg.line()
          .x(function (d) {
            return x2(moment(d.at));
          })
          .y(function (d) {
            return y2(d.value);
          });

        var graph = d3.select(element[0])
          .append('svg')
          .attr('width', scope.width)
          .attr('height', scope.height);

        var xAxis = d3.svg.axis().scale(x).orient('bottom'),
          xAxis2 = d3.svg.axis().scale(x2).orient('bottom'),
          yAxis = d3.svg.axis().scale(y).orient('left');

        var brush = d3.svg.brush()
          .x(x2)
          .on('brush', brushed);

        var focus = graph.append('g')
          .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

        var context = graph.append('g')
          .attr('transform', 'translate(' + margin2.left + ',' + margin2.top + ')');

        focus.append('defs').append('clipPath')
          .attr('id', 'clip')
          .append('rect')
          .attr('width', width)
          .attr('height', height);

        focus.append('g')
          .data([scope.data])
          .attr('clip-path', 'url(#clip)')
          .append('path')
          .attr('d', line)
          .attr('class', 'line');

        focus.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height + ')')
          .call(xAxis);

        focus.append('g')
          .attr('class', 'y axis')
          .call(yAxis);

        context.append('path')
          .data([scope.data])
          .attr('d', line2)
          .attr('class', 'line');

        context.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height2 + ')')
          .call(xAxis2);

        context.append('g')
          .attr('class', 'x brush')
          .call(brush)
          .selectAll('rect')
          .attr('y', -6)
          .attr('height', height2 + 7);

        function brushed() {
          x.domain(brush.empty() ? x2.domain() : brush.extent());
          focus.select('path.line').attr('d', line);
          focus.select('.x.axis').call(xAxis);
        }

        function updateGraph () {
           // update x axis
          x.domain([scope.start, scope.end]);
          x2.domain([scope.start, scope.end]);
          xAxis.scale(x);
          xAxis2.scale(x2);

          focus.selectAll('g.x.axis').call(xAxis);
          context.selectAll('g.x.axis').call(xAxis2);

          // update y axis
          var min = d3.min(scope.data, function (d) {return d.value; })
          var max = d3.max(scope.data, function (d) {return d.value; })
          var thres = Math.abs(max-min);

          y.domain([min - thres, max + thres]);
          y2.domain([min - thres, max + thres]);

          yAxis.scale(y);

          focus.selectAll('g.y.axis').call(yAxis);

          //update line
          focus.selectAll('path.line')
            .data([scope.data])
            .attr('d', line);

          context.selectAll('path.line')
            .data([scope.data])
            .attr('d', line2);
        }

        scope.$watch('data', function () {
          var last = scope.data.length > 0 ? moment(_.last(scope.data).at) : null;

          if (last && last > scope.end) {
            scope.updateTime(last, moment(last).add(scope.unit, scope.period));
            scope.data = [_.last(scope.data)];
          }
          updateGraph();
        });
      }
    };
  }]).

  directive('paginator', function () {
    return {
      controller: 'DataCtrl',
      restrict: 'E',
      template: '<button class="forward" ng-disabled="stream" ng-click="forward()">Page up</button>' +
                '<button class="back" ng-click="back()">Page down</button>'
    };
  });

График обновляется автоматически с помощью socket.io в контроллере. Я безуспешно пытался прикрепить определения к «svg» вместо «g». Любые идеи?

Я использую Angular 1.2.2.

26.11.2013

  • Вы убедились, что SVG, сгенерированный angular, содержит defs? 26.11.2013
  • Да, код в jsfiddle — это копирование и вставка из вывода angular. 27.11.2013

Ответы:


1

Наконец, изолировав код в другом файле и упростив его, я нашел причину этого странного поведения:

В <head> у меня было:

<head>
  <meta charset="utf8">
  <title>Real time context aware graphics display</title>
  <link rel="stylesheet" href="/stylesheets/app.css">
  <link rel="stylesheet" href="/stylesheets/graph.css"><base href="/">
  <base href="/">
  <style type="text/css"></style>
</head>

Объявление, когда я удалил <base href="/">, все работало отлично. Я не знаю точно причину.

28.11.2013
  • Вы указали относительный URL-адрес — url(#clip) он преобразуется в абсолютный URL-адрес, а базовая директива меняет способ работы. 28.11.2013
  • @RobertLongson Мне нужно <base href="/"> в моем проекте. Я также хочу использовать clipPaths. Как бы вы решили это? 29.01.2014
  • Хорошо :-) Вопрос здесь< /б>. 29.01.2014
  • Обходной путь, который я использовал, заключался в том, чтобы добавить относительный URL-адрес перед #clip либо 'url(' + $location.path() + '#clip)' в контроллер, либо, если вам это нужно в html, добавить $scope.path = $location.path() в контроллер и clip-path="url({{path}}#clip)" в элемент. 09.08.2014
  • Еще одно небольшое дополнение к ответу @morloch: если у вас есть '?' и параметры запроса в URL-адресе (также известные как значения поиска), вам нужно будет использовать $locaiton.url() вместо $location.path(). Это будет выглядеть примерно так: url($location.url() + #clip) 11.11.2015
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...


    © 2024 squeak.ru, Squeak.ru - шаблоны программирования