Libgdx手写签名
1、原理是通过描点来实现,点之间通过贝塞尔曲线来拟合。
'''package com.mytian.mgarden.stages.main;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Bezier;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.mytian.mgarden.utils.libgdxutil.BaseStage;
/**
- Created by gang.zhou on 2018/1/22.
*/
public class DrawingStage extends BaseStage {
ShapeRenderer renderer;
com.badlogic.gdx.utils.Array<Array<TimePoint>> paths = new com.badlogic.gdx.utils.Array<>();
com.badlogic.gdx.utils.Array<TimePoint> points = new com.badlogic.gdx.utils.Array<>();
@Override
public void onLoadFinish() {
renderer = new ShapeRenderer();
renderer.setAutoShapeType(true);
renderer.setColor(Color.RED);
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
points.clear();
Vector2 vector2 = screenToStageCoordinates(new Vector2(screenX, screenY));
points.add(new TimePoint(vector2));
return true;
}
@Override
public void draw() {
super.draw();
renderer.setProjectionMatrix(getCamera().combined);
renderer.begin(ShapeRenderer.ShapeType.Filled);
for (Array<TimePoint> path : paths) {
if (path.size == 1) {
renderer.circle(path.get(0).position.x, path.get(0).position.y, path.get(0).radius);
} else {
for (int i = 0; i < path.size; i++) {
renderer.circle(path.get(i).position.x, path.get(i).position.y, path.get(i).radius);
}
}
}
if (points.size == 1) {
renderer.circle(points.get(0).position.x, points.get(0).position.y, points.get(0).radius);
} else {
for (int i = 0; i < points.size; i++) {
renderer.circle(points.get(i).position.x, points.get(i).position.y, points.get(i).radius);
}
}
renderer.end();
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
paths.add(new Array<>(points));
points.clear();
return true;
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
final Vector2 vector2 = screenToStageCoordinates(new Vector2(screenX, screenY));
final TimePoint point = new TimePoint(vector2);
final TimePoint pPoint = points.get(points.size - 1);
float n = (float) Math.sqrt(Math.pow((point.position.x - pPoint.position.x), 2)
+ Math.pow((point.position.y - pPoint.position.y), 2));
float v = n / (Math.max(point.time - pPoint.time, 1));
point.radius = Math.max(5f / (v + 1), 1f);
final QuadraticBezier bezier = new QuadraticBezier(pPoint.position, new Vector2((pPoint.position.x + point.position.x) / 2.0f
, (pPoint.position.y + point.position.y) / 2.0f), point.position);
for (int i = 0; i < n; ++i) {
TimePoint timePoint = new TimePoint(bezier.apply(1f * i / n));
timePoint.radius = Math.max(pPoint.radius + (point.radius - pPoint.radius) * (1f * i / n)
, 1);
points.add(timePoint);
}
points.add(point);
return true;
}
/**
*
*/
public static class QuadraticBezier extends Bezier {
public Vector2 p0;
public Vector2 p1;
public Vector2 p2;
public QuadraticBezier(Vector2 p0, Vector2 p1,
Vector2 p2) {
this.p0 = p0;
this.p1 = p1;
this.p2 = p2;
}
public Vector2 apply(float f) {
float f1 = 1.0F - f;
float f2 = f1 * f1;
float f3 = f * (2.0F * f1);
float f4 = f * f;
final Vector2 tmpVec = new Vector2();
tmpVec.x = f2 * p0.x + f3 * p1.x + f4 * p2.x;
tmpVec.y = f2 * p0.y + f3 * p1.y + f4 * p2.y;
return tmpVec;
}
}
@Override
public boolean keyDown(int keyCode) {
if (keyCode == Input.Keys.ENTER) {
paths.clear();
points.clear();
}
return super.keyDown(keyCode);
}
@Override
public void onBack() {
paths.clear();
points.clear();
}
@Override
public void dispose() {
super.dispose();
renderer.dispose();
}
static class TimePoint {
public Vector2 position;
public long time = System.nanoTime();
public float radius = 5;
public TimePoint(Vector2 position) {
this.position = position;
time = System.currentTimeMillis();
}
}
}
'''