Как сделать подобный эффект на CANVAS?

Вот отличный пример, но в исходнике не нашел, что за это отвечает. https://yandex.ru/company/
Нашел атрибут в родителе canvas - apiLivequeries
Думал что там живые запросы, но скрипт работает и без интернета, да собственно и нужен набор из фраз пятнадцати например, что бы появлялись с таким эффектом. Буду очень благодарен!
Создал на сервере так же директорию /company/_/api/livequeries/
В ней отдаю json
$json = json_decode(file_get_contents('./text.json'), true);
echo json_encode($json, JSON_UNESCAPED_UNICODE);

Но в итоге пустота в канвасе.
В примере яндекса, в атрибуте у них сделано так (именно с & quot ;)
data-bem="{"livequeries":{"apiLivequeries":"/company/_/api/livequeries/"}}"
  • Вопрос задан
  • 486 просмотров
Пригласить эксперта
Ответы на вопрос 2
Если вам не обязательно canvas - то можно использовать что-то такое www.mattboldt.com/demos/typed-js.
А вообще - гуглите в сторону "js typing effect".
Ответ написан
@GreatRash
Код, который отвечает за отрисовку (прогнал через деобфускатор):

BEM.DOM.decl("livequeries", {
  minItems : 100,
  pixelRatio : void 0,
  /**
   * @param {number} value
   * @return {?}
   */
  _size : function(value) {
    return value * this.pixelRatio;
  },
  onSetMod : {
    /**
     * @return {undefined}
     */
    js : function() {
      var self = this;
      var c = this.$canvas = this.elem("queries");
      var canvas = this.canvas = c[0];
      var valueAccessor = this.params.rowsCount || 10;
      var mQueries = this.params.colsCount || 100;
      var s = this.params.maxQueries || 20;
      var asserterNames = this.params.blindAreas || [[30, 2, 40, 6]];
      var fn = this.mQueries = new i(mQueries, valueAccessor, s);
      this.context = canvas.getContext("2d");
      this.rgb = a(c.css("color"));
      asserterNames.forEach(function(arr) {
        fn.disable(arr[0], arr[1], arr[2], arr[3]);
      });
      $(window).resize(function() {
        self.rescale();
      });
      this.startRenderingLoop();
    }
  },
  /**
   * @return {undefined}
   */
  startRenderingLoop : function() {
    var parms = this;
    if (!this.isRenderingRunning()) {
      /** @type {number} */
      this.renderingLoopTimer = setInterval(function() {
        /** @type {number} */
        var pixelRatio = window.devicePixelRatio;
        if (parms.pixelRatio !== pixelRatio) {
          /** @type {number} */
          parms.pixelRatio = pixelRatio;
          parms.rescale();
        }
        parms.doLayout();
      }, 1E3 / 30);
    }
  },
  /**
   * @return {undefined}
   */
  stopRenderingLoop : function() {
    window.clearInterval(this.renderingLoopTimer);
    /** @type {null} */
    this.renderingLoopTimer = null;
  },
  /**
   * @return {?}
   */
  isRenderingRunning : function() {
    return Boolean(this.renderingLoopTimer);
  },
  /**
   * @return {undefined}
   */
  rescale : function() {
    var $this = this.$canvas;
    var width = $this.width();
    var height = $this.height();
    var canvas = this.canvas;
    var a = this.mQueries;
    var value = o($this.css("font-size"));
    /** @type {Array} */
    this.cellSize = [Math.floor(width / a.width), Math.floor(height / a.height)];
    this.font = $this.css("font-style") + " " + $this.css("font-weight") + " " + this._size(value[0]) + value[1] + " " + $this.css("font-family");
    canvas.width = this._size(width);
    canvas.height = this._size(height);
  },
  /**
   * @return {undefined}
   */
  doLayout : function() {
    var data;
    var actor;
    /** @type {null} */
    var file = null;
    var self = this.mQueries;
    var files = self.queries;
    var ctx = this.context;
    var setFillStyle = this.rgb;
    var cellSize = this.cellSize;
    this.clearRect(0, 0, 9999, 9999);
    for (file in files) {
      if (files.hasOwnProperty(file)) {
        data = files[file];
        actor = data.place;
        data = data.query;
        if (data.relevance) {
          if (data.state) {
            /** @type {string} */
            ctx.textAlign = "left";
            /** @type {string} */
            ctx.textBaseline = "center";
            ctx.font = this.font;
            this.setFillStyle(setFillStyle[0], setFillStyle[1], setFillStyle[2], data.relevance);
            this.fillText(data.state, actor[0] * cellSize[0], actor[1] * cellSize[1] + cellSize[1] / 2, data.text.length * cellSize[0]);
          }
        }
      }
    }
    if (self.stack.length < this.minItems) {
      if (!this._loading) {
        this.pullQueries();
      }
    }
    if (null === file) {
      this.stopRenderingLoop();
    }
  },
  /**
   * @param {?} text
   * @param {number} x
   * @param {number} y
   * @param {number} width
   * @return {undefined}
   */
  fillText : function(text, x, y, width) {
    x = this._size(x);
    y = this._size(y);
    width = this._size(width);
    this.context.fillText(text, x, y, width);
  },
  /**
   * @param {number} x
   * @param {number} y
   * @param {number} width
   * @param {number} height
   * @return {undefined}
   */
  clearRect : function(x, y, width, height) {
    x = this._size(x);
    y = this._size(y);
    width = this._size(width);
    height = this._size(height);
    this.context.clearRect(x, y, width, height);
  },
  /**
   * @param {?} color
   * @param {?} f
   * @param {?} fillStyle
   * @param {?} e
   * @return {undefined}
   */
  setFillStyle : function(color, f, fillStyle, e) {
    this.context.fillStyle = n(color, f, fillStyle, e);
  },
  /**
   * @return {undefined}
   */
  pullQueries : function() {
    var self = this;
    /** @type {boolean} */
    this._loading = true;
    $.get(this.params.apiLivequeries).then(function(pair) {
      /** @type {boolean} */
      self._loading = false;
      self.mQueries.store(pair.livequeries);
      if (!self.isRenderingRunning()) {
        self.startRenderingLoop();
      }
    }, function() {
      setTimeout(function() {
        self.pullQueries();
      }, 5E3);
    });
  }
});
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы