我之前有一个基于HTML5画布的应用程序,我最近转换为使用Kinetic JS。我能够通过在包含的div上使用overflow:auto来启用桌面浏览器和IOS中的滚动。由于转换为使用Kinetic滚动不再适用于移动/ iPad设备。
虽然我有点陷入困境,但我尝试过几个不同的方法解决这个问题。首先我尝试使用touchscroll,但出于各种原因,这对我来说并不起作用(事情确实滚动了,因为库导致了其他问题)。接下来我尝试将-webkit-overflow-scrolling:touch选项添加到我的div风格中,虽然这似乎没有任何效果。
是否有标准方法滚动比您的可视区域/ div大的Kinetic JS画布?
这是一个例子。如果您在IOS设备(iPad,iPhone等)上查看该示例,您会注意到顶部画布不会在div中滚动,而底部画布不会在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似乎阻止了移动浏览器执行其默认滚动行为。如果&#34;我&#34;已经注册了touchmove事件,这可能是可取的。如果Kinetic没有注册和处理我不感兴趣的事件,那就太好了。
_touchmove: function(evt) {
this._setUserPosition(evt);
var dd = Kinetic.DD;
evt.preventDefault();
我可以在此处演示此问题:http://jsfiddle.net/blueshirts/P9RaT/28/
答案 0 :(得分:1)
我认为这是Kinetic JS中的一个基本错误。如果我知道这种情况,我就不会开始使用kinetic JS来开展一个雄心勃勃的项目,因为它甚至无法完成基础工作。
由于没有来自任何Kinetic团队的回复,我将转换到像fabric.js这样不那么错误的库。
答案 1 :(得分:0)
不确定我喜欢这个选项,但它比使用众多滚动库中的一个更好。我能够通过扩展默认的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);
}
}
答案 2 :(得分:0)
我可能不完全理解这个问题,但为什么不在舞台上添加'draggable: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
});
我正在使用相同的方法,其中我的画布是视口大小的几倍,并且使用'draggable:true'我可以滚动画布图像。
答案 3 :(得分:0)
我在使用KineticJS创建的地图上在iPad / iPhone上滚动时遇到了同样的问题。
这对我有用:stage.setListening(false);
我在这里找到了这个解决方案: