Scale KineticJS Stage with Browser Resize?

我们两清 提交于 2019-12-03 17:35:43

Sure!

But, be careful about scaling the Kinetic container element with CSS (as Bootstrap does) because the browser will resize by "stretching" the pixels rather than letting Kinetic redraw the pixels.

Since html canvas (and therefore Kinetic objects) are really just pixels, the common warnings about resizing also apply when scaling the Kinetic container.

  • The drawings will distort if you scale horizontally and vertically by different factors.
  • Drawings that are scaled up/down by a large factor may get the "jaggies".

A better way to resize your kinetic stage is to:

  • Resize the kinetic container element proportionally
  • Let Kinetic know its container is resizing with .setWidth and .setHeight
  • Use .setScaleX and setScaleY followed by stage.draw to scale the stage and all its components.
klenwell

Here's an implemetation of the method recommended by markE. It also incorporates techniques described in this article on auto-resizing HTML5 games.

Find a working demo here: http://jsfiddle.net/klenwell/yLDVz/

var iPadLandscapeDimensions = {
  width: 1024,
  height: 768
};

var KineticScreenAutoSize = (function() {
  var self = {
    $container: null,
    stage: null,
    baseWidth: 0,
    baseHeight: 0
  };

  var init = function(selector, baseWidth, baseHeight) {
    self.$container = $(selector);
    self.baseWidth = baseWidth;
    self.baseHeight = baseHeight;
    initStage();
  };

  var initStage = function($container) {
    self.stage = new Kinetic.Stage({
      container: self.$container.attr('id'),
      width: self.baseWidth,
      height: self.baseHeight
    });
  };

  /*
   * Screen-Sizing Methods
   */
  var autoSize = function() {
    // Style required for resizeScreen below
    self.$container.css({
      position: 'absolute',
      left: '50%',
      top: '50%',
      width: '100%',
      height: '100%'
    });

    // Resize automatically
    window.addEventListener('resize', resizeStageToFitScreen, false);
    window.addEventListener('orientationchange', resizeStageToFitScreen, false);

    // Resize now
    resized = resizeStageToFitScreen();
  };

  var resizeStageToFitScreen = function() {
    /*
     * Following directions here: https://stackoverflow.com/a/19645405/1093087
     */
    var resized = calculateResize();

    // Resize the kinetic container element proportionally
    resized.cssSettings = {
      left: resized.xToCenter + 'px',
      top: resized.yToCenter + 'px',
      width: resized.width,
      height: resized.height,
    }
    self.$container.css(resized.cssSettings);

    // Let Kinetic know its container is resizing with .setWidth and .setHeight
    self.stage.setSize(resized);

    // Use .setScaleX and setScaleY followed by stage.draw to scale the stage
    // and all its components.
    self.stage.scaleX(resized.xScale);
    self.stage.scaleY(resized.yScale);

    self.stage.draw();
    return resized;
  };

  var calculateResize = function() {
    var resized = {
      width: 0,
      height: 0,
      xScale: 0,
      yScale: 0,
      xToCenter: 0,
      yToCenter: 0
    }

    var windowWidth = window.innerWidth,
        windowHeight = window.innerHeight,
        desiredWidthToHeightRatio = self.baseWidth / self.baseHeight,
        currentWidthToHeightRatio = windowWidth / windowHeight;

    if ( currentWidthToHeightRatio > desiredWidthToHeightRatio ) {
      resized.width = windowHeight * desiredWidthToHeightRatio;
      resized.height = windowHeight;
    }
    else {
      resized.width = windowWidth;
      resized.height = windowWidth / desiredWidthToHeightRatio;
    }

    resized.xToCenter = (window.innerWidth - resized.width) / 2;
    resized.yToCenter = (window.innerHeight - resized.height) / 2;
    resized.xScale = resized.width/self.baseWidth,
    resized.yScale = resized.height/self.baseHeight;

    return resized;
  };

  /*
   * Public API
   */
  var publicAPI = {
    init: init,
    stage: function() { return self.stage },
    autoSize: autoSize
  }

  return publicAPI;

})();

// Launch Resize
$(document).ready(function() {
  KineticScreenAutoSize.init(
    'div#stage-container',
    iPadLandscapeDimensions.width,
    iPadLandscapeDimensions.height
  );
  KineticScreenAutoSize.autoSize();
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!