java - 放大画布中的某个点,其中所有内容都基于某个点
问题描述
好吧,有点奇怪。我会尽力解释。我正在 Android (Java) 上构建游戏。我只是先制定意见。我要做的第一件事是太阳系视图(自上而下,二维,无倾斜)。我已经正确地按比例显示了所有行星和恒星。我可以平移和缩放。唯一的问题是,我设置所有要绘制的圆圈的方式,它们都基于一个点(星星所在的位置),当我“缩放”/“平移”时,我实际上并没有缩放/平移。对于平移,我只是在移动一切旋转的点,对于缩放,我没有缩放整个画布(尝试过,没有成功)我正在调整元素的大小绘图,按照缩放。
所以我有一个从屏幕中间开始的“星星”,这个点叫做轨道位置。还有一个从 开始的缩放变量1f
。星星画得很简单——canvas.drawCircle((float)orbitLocation.x, (float)orbitLocation.y, this.radius * zoom, this.paint);
每个行星的位置如下:
canvas.drawCircle(getPlanetX(angle, orbitLocation, zoom), getPlanetY(angle, orbitLocation, zoom), this.radius * zoom, this.paint);
getPlanetX
getPlanetY
看起来像这样:
private float getPlanetX(double angle, Point orbitingPoint, float zoom) {
return orbitingPoint.x + (this.distance * Constants.AU * zoom) * (float)Math.sin(angle);
}
private float getPlanetY(double angle, Point orbitingPoint, float zoom) {
return orbitingPoint.y + (this.distance * Constants.AU * zoom) * (float)Math.cos(angle);
}
Constants.AU
是天文单位的常量 int 11507
- 用于适当的缩放。
现在我在缩放时遇到的问题是,如果我平移,然后缩放,整个事情都会从轨道位置缩放,而不管我试图放大的位置,所以无论我的屏幕中间是什么,很快被扔出屏幕。
期望的结果。让屏幕中心的任何东西(或夹在手指之间,无论哪种方式),保持在屏幕的中心,并且轨道点会根据自身进行调整。
这是我的触摸事件的相关部分:
if (touchCount == 2) { // if pinch
if (startZoomTouchPoint != null) {
float newDistance = getDistance(event, 0, 1);
float distanceDifference = (startZoomDistance - newDistance);
zoom -= distanceDifference * (zoom / 100);
if (zoom < MIN_ZOOM) {
zoom = MIN_ZOOM;
}
// Point zoomCenter = getZoomCenter(event);
// int yOrbitOffset = orbitLocation.y - zoomCenter.y;
// int xOrbitOffset = orbitLocation.x - zoomCenter.x;
// orbitLocation.x += xOrbitOffset + Constants.AU * zoom;
// orbitLocation.y += yOrbitOffset + Constants.AU * zoom;
startZoomDistance = newDistance;
updateStartZoomTouchPoint(event);
}
}
中间的那些注释行是我实现目标的最新尝试。
每次我尝试时,我要么移动orbitLocation
太多,要么不够,或者它奇怪地移动。
getZoomCenter
从字面上看,只是在两根手指之间。如果这样更容易,我们可以使用屏幕的中心。
好吧,这就是我所拥有的。如果您需要更多信息,请告诉我。
解决方案
请看下面的代码片段
private ScaleGestureDetector mScaleDetector;
private float zoom = 1.f;
public MyCustomView(Context mContext){
...
// View code goes here
...
mScaleDetector = new ScaleGestureDetector(context, new
ScaleListener());
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
return true;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(zoom, zoom);
...
// onDraw() code goes here
...
canvas.restore();
}
private class ScaleListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
zoom = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
基本上,您需要根据从触摸事件获得的缩放值来缩放画布。你可以这样做
- 保存画布
- 缩放画布
- 画出你正在画的东西
- 恢复画布
您可以设置缩放手势检测器的响应。之后调用无效。
欲了解更多信息,请访问https://developer.android.com/training/gestures/scale
推荐阅读
- ios - 如何在 iOS 中创建 ByteBuffer?
- statistics - 方差分析不显着但系数变量显着?
- vue.js - Vue不显示来自数据对象的数据
- python - 使用 xgboost 时出现问题,错误 - “OSError: [WinError 126] The specified module could not be found”
- c++ - 检查失败:1 == NumElements() (1 vs. 2)必须有一个单元素张量
- google-cloud-platform - 在 Google 云实例删除时通知电子邮件
- javascript - 计算多行的keyup(通过按钮单击创建的行)
- java - 强制接口的所有扩展和实现使用有界通用输入
- java - 无法在文本框中输入文本
- c# - 如何更改面板中按钮的位置?