移动端的滚动和原生事件
Konva 默认阻止指针的浏览器默认行为,代价是页面在画布上滑不动。这个取舍可以调整。
用法
默认情况下,Konva将阻止所有指针与舞台交互的默认行为。
当您尝试在移动设备上拖放形状时,这将防止意外滚动页面。
但在某些情况下,您可能希望保留浏览器事件的默认行为。 在这种情况下,您可以将形状的preventDefault属性设置为false。
说明:如果您使用移动设备,请尝试按每个矩形滚动页面。
绿色 - 应防止默认行为(无页面滚动)。
红色 - 将保持默认行为(滚动工作)。
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@10/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Mobile Scrolling and Native Events Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var defaultBehaviourRect = new Konva.Rect({
width: 100,
height: 100,
fill: 'green'
});
layer.add(defaultBehaviourRect);
var noPreventDefaultRect = new Konva.Rect({
x: 200,
y: 50,
width: 100,
height: 100,
fill: 'red',
preventDefault: false
});
layer.add(noPreventDefaultRect);
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>
常见问题
为什么在画布上滑动,页面不跟着滚?
这是 Konva 的有意设计。移动端如果不阻止默认行为,用户想拖动图形时页面会跟着滚, 两种意图混在一起,拖拽几乎没法用。
所以 Konva 默认对指针交互调用 preventDefault。代价就是画布区域「吞掉」了页面滚动。
怎么让页面能正常滚动?
把图形的 preventDefault 设为 false:
shape.preventDefault(false);
这样触摸该图形时浏览器的默认行为(滚动)照常发生。
注意这是按节点设置的,不是全局开关。舞台上没有图形的空白区域行为由容器的
CSS touch-action 决定,与这个属性无关。
放行之后拖拽图形时页面也在滚,怎么办?
这正是两者的根本矛盾:同一个手势,系统无法判断用户想拖图形还是想滚页面。
常见折中是按图形区分——可拖拽的图形保持 preventDefault: true,
纯展示的图形设为 false。用户在展示区滑动能滚页面,在可操作区拖拽不会误滚。
另一种做法是限制方向:容器设 touch-action: pan-y,允许垂直滚动,
水平手势留给画布。适合横向拖拽的场景。
国内环境注意事项
国内的 App 内置浏览器大多加了自己的下拉刷新与边缘返回手势,它们的优先级高于页面逻辑。
下拉刷新最容易出问题:画布位于页面顶部时,向下拖拽图形会先触发刷新。
preventDefault 在部分内核下拦不住它,因为手势识别发生在更底层。
实践中的办法是让画布不要紧贴页面顶部,上方留一块内容区。
边缘返回同理,从屏幕左右边缘开始的横向拖拽会被判为返回手势。
把可拖拽内容与屏幕边缘保持一定距离,或者在容器上设 touch-action: none 争夺控制权。
这些行为在不同版本、不同机型上表现不一致,只能靠实机验证。 如果产品主要跑在微信里,至少要在 iOS 与 Android 各测一台。