2

私は以前、最近 Kinetic JS を使用するように変換した HTML5 キャンバス ベースのアプリケーションを持っていました。デスクトップ ブラウザーと IOS でスクロールを有効にするには、単にオーバーフローを使用するだけで済みました: auto を囲む div. キネティック スクロールの使用に切り替えたため、モバイル/iPad デバイスでは機能しなくなりました。

少し行き詰まっていますが、いくつかの異なる方法でこの問題を回避しようとしました。最初に touchscroll を使用してみましたが、さまざまな理由でこれはうまくいきませんでした (ライブラリが他の問題を引き起こしているにもかかわらず、物事はスクロールしました)。次に、 -webkit-overflow-scrolling: touch オプションを div のスタイルに追加してみましたが、効果はないようです。

表示可能な領域/div より大きい Kinetic JS キャンバスをスクロールする標準的な方法はありますか?

ここに例があります。この例を iOS デバイス (iPad、iPhone など) で表示すると、上部のキャンバスは div 内でスクロールされず、下部のキャンバスはスクロールされることがわかります。

http://jsfiddle.net/blueshirts/uERVq/26/

<!-- KineticJS canvase, won't scroll on IOS devices. -->
<div id="container" style="overflow: auto; width: 400px; height: 400px; background-    color: gray">
</div>

<br/>

<!-- Vanilla HTML5 Canvas, does scroll on IOS devices. -->
<div id="canvasContainer"
     style="width: 400px; height: 400px; overflow: auto; background-color: red">
    <canvas id="vanillaCanvas"
            width="800" height="600">
    </canvas> 
</div>

// Create a stage instance that is larger than its parent div.
var stage = new Kinetic.Stage({
    container: 'container',
    width: 800,
    height: 600
});

// Create a layer.
var layer = new Kinetic.Layer();

// Add some text...
var text = new Kinetic.Text({
    text: "KineticJS generated Canvas that won't scroll to IOS touches...",
    x: 0,
    y: 0,
    fontSize: 12,
    fontFamily: 'Calibri',
    textFill: 'Black'                
});
layer.add(text);

// Add a rectangle to the layer so you can see if the content scrolls.
var rect = new Kinetic.Rect({
    x: 50,
    y: 50,
    width: 200,
    height: 100,
    fill: "yellow",
    stroke: "black",
    strokeWidth: 7
});
layer.add(rect);

// Add the layer to the stage.
stage.add(layer);


// Create a "vanilla" canvas instance and draw the same rectangle on it.
var canvas = document.getElementById('vanillaCanvas');
var context = canvas.getContext('2d');

context.beginPath();
context.rect(50, 50, 200, 100);
context.fillStyle = 'yellow';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();

編集:

間違っている可能性がありますが、この問題は、Kinetic が Stage クラスの touchmove イベント (およびその他) に登録していることが原因であると思われます。ハンドラーでは、モバイルブラウザーがデフォルトのスクロール動作を実行するのを止めているように見える preventDefault を実行します。「私」が touchmove イベントに登録していた場合、これはおそらく望ましいことです。私が興味のないイベントを Kinetic が登録して処理しなければよかったと思います。

 _touchmove: function(evt) {
     this._setUserPosition(evt);
     var dd = Kinetic.DD;
     evt.preventDefault();

ここでこの問題を実証できます: http://jsfiddle.net/blueshirts/P9RaT/28/

4

4 に答える 4

1

これは Kinetic JS の根本的なバグだと思います。これが事実であることを知っていれば、キネティック JS を使用して、基本的なことさえできない野心的なプロジェクトに着手することはしなかったでしょう。

どの Kinetic チームからも応答がないため、fabric.js のようなバグの少ないライブラリに切り替えます。

于 2014-06-26T09:41:31.743 に答える
0

問題を完全には理解していないかもしれませんが、ステージに「ドラッグ可能: true」を追加してみませんか?

// Create a stage instance that is larger than its parent div.
var stage = new Kinetic.Stage({
    container: 'container',
    width: 800,
    height: 600,
    draggable: true
});

私はキャンバスがビューポートのサイズの数倍であるこの同じ方法を使用しており、「ドラッグ可能:真」でキャンバス画像をスクロールできます。

于 2014-01-09T04:27:19.237 に答える
0

KineticJS を使用して作成したマップを iPad/iPhone でスクロールすると、同じ問題が発生しました。

これは私にとってはうまくいきました:stage.setListening(false);

ここでこの解決策を見つけました:

https://github.com/ericdrowell/KineticJS/pull/510

于 2014-09-27T01:09:11.227 に答える
0

多くのスクロール ライブラリの 1 つを使用するよりも優れていますが、このオプションが好きかどうかはわかりません。この問題は、デフォルトの Stage クラスを拡張し、モバイル デバイスを使用していないときにのみ evt.preventDefault() を実行することで回避できます。これまでのところ私の使用法を満たしているように見えますが、これがどのような悪影響を引き起こす可能性があるかはわかりません. デフォルトの動作を変更する簡単な方法があればいいのですが。

Kinetic.Global.extend(MyStage, Kinetic.Stage);
function MyStage(mobile, config) {
    this.mobile = mobile;
    this._initStage(config);
}
MyStage.prototype._touchstart = function(evt) {
    this._setUserPosition(evt);
    if (this.mobile) {
        evt.preventDefault();
    }
    var obj = this.getIntersection(this.getUserPosition());

    if(obj && obj.shape) {
        var shape = obj.shape;
        this.tapStart = true;
        shape._handleEvent('touchstart', evt);
    }

    /*
                         * init stage drag and drop
                         */
    if(Kinetic.DD && this.attrs.draggable) {
        this._initDrag();
    }
}
MyStage.prototype._touchmove = function(evt) { // Override the default touchmove handler.
    this._setUserPosition(evt);
    var dd = Kinetic.DD;
    if (this.mobile) {
        evt.preventDefault();
    }
    var obj = this.getIntersection(this.getUserPosition());
    if(obj && obj.shape) {
        var shape = obj.shape;
        shape._handleEvent('touchmove', evt);
    }

    // start drag and drop
    if(dd) {
        dd._startDrag(evt);
    }
}
于 2012-11-22T04:15:10.740 に答える