React-Native画线平滑处理
2016-10-12 10:59
253 查看
参考:http://blog.csdn.net/pz789as/article/details/52795275
这次开发要手写画线,我们一般画线的时候是直接获取屏幕上的点,然后利用ART绘制出一天路径线:
这里主要是在AddUsePoint里面对触摸点进行处理,在touchmove之后,每次都要保存好获得到的点,然后取差值,进行计算
上面代码运行后,得到的线条是这样的:
看到结果后,是不是很不理想,我们想要的不是横平竖直啊,怎么使它们变得平滑呢,我开始想的是贝塞尔曲线,于是在网上找,终于找到一个算法,叫B样条曲线算法,其实这个就是贝塞尔的一种,原理大概就是根据其中几个点进行一个公式算法,得到这些点之间的其他点。
于是在上面的代码进行改善,修改AddUsePoint,添加B样条曲线算法,先看看效果:
效果很不错哦~
代码如下:
Utils类《-点这里查看,我这里贴出来
这次开发要手写画线,我们一般画线的时候是直接获取屏幕上的点,然后利用ART绘制出一天路径线:
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import { StyleSheet, Text, View, PanResponder, TouchableOpacity, StatusBar, ART, } from 'react-native'; const { Shape, Group, Transform, Surface, Path, Pattern, LinearGradient, RadialGradient, // Text, ClippingRectangle, } = ART; import Utils from './Utils'; let cv = { status_norm: 0, status_auto: 1, status_pause: 2, touch_begin: 0, touch_move: 1, touch_ended: 2, }; export default class DrawLayout extends Component { constructor(props){ super(props); this._panResponder = {}; this.mousePosition = null; this.lastMousePostion = null; this.arrOrgPoint = []; this.arrUsedPoint = []; this.nowR = 10; this.blnCanDraw = false; this.showPoints = null; this.status = cv.status_norm; this.wrongCount = 0; this.state={ blnUpdate: false, }; } setUpdate(){ this.setState({ blnUpdate: !this.state.blnUpdate, }); } componentWillMount() { this._panResponder = PanResponder.create({ onStartShouldSetPanResponder: this.onStartShouldSetPanResponder.bind(this), onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder.bind(this), onPanResponderGrant: this.onPanResponderGrant.bind(this), onPanResponderMove: this.onPanResponderMove.bind(this), onPanResponderRelease: this.onPanResponderRelease.bind(this), onPanResponderTerminate: this.onPanResponderTerminate.bind(this), }); } componentDidMount() { this._autoUpdate = setInterval(this.autoUpdate.bind(this), 1/60); } componentWillUnmount() { this._autoUpdate && clearInterval(this._autoUpdate); } onStartShouldSetPanResponder(e, g){ if (this.status == cv.status_auto || this.status == cv.status_pause){ return false; } return true; } onMoveShouldSetPanResponder(e, g){ if (this.status == cv.status_auto || this.status == cv.status_pause){ return false; } return true; } onPanResponderGrant(e, g){ if (g.numberActiveTouches == 1){ this.mousePosition = { x: e.nativeEvent.locationX, y: e.nativeEvent.locationY }; this.ResetDrawPoint(); this.AddUsePoint(this.mousePosition, cv.touch_begin); } } onPanResponderMove(e, g){ if (g.numberActiveTouches == 1){ this.mousePosition = { x: e.nativeEvent.locationX, y: e.nativeEvent.locationY }; var s = Utils.DisP(this.mousePosition, this.lastMousePostion); if (s >= 1){ this.AddUsePoint(this.mousePosition, cv.touch_move); } } } onPanResponderRelease(e, g){ this.endPanResponder(e, g); } onPanResponderTerminate(e, g){ this.endPanResponder(e, g); } endPanResponder(e, g){ this.mousePosition = { x: e.nativeEvent.locationX, y: e.nativeEvent.locationY }; this.AddUsePoint(this.mousePosition, cv.touch_ended); } ResetDrawPoint(){ this.arrOrgPoint = []; this.arrUsedPoint = []; this.nowR = 5; this.blnCanDraw = false; this.showPoints = null; } AddUsePoint(pos, kind){ if (kind == cv.touch_begin){ this.lastMousePostion = this.mousePosition; this.arrOrgPoint.push(pos); this.AddSinglePoint(pos, this.nowR); this.blnCanDraw = true; }else if (this.blnCanDraw){ this.arrOrgPoint.push(pos); var blnSet = false; if (this.arrOrgPoint.length > 2){ var count = Utils.DisP(this.lastMousePostion, pos); if (count > 1){ for(var i=0;i<count;i++){ var p = Utils.LerpP(this.lastMousePostion, pos, (i+1)/count); this.AddSinglePoint(p, this.nowR); } } blnSet = true; }else{ var count = Utils.DisP(this.lastMousePostion, pos); if (count > 1){ var c = Math.ceil(count); for(var i=0; i < c; i++){ if (i == c - 1){ this.AddSinglePoint(pos, this.nowR); }else{ var p = Utils.LerpP(this.lastMousePostion, pos, (i + 1) / c); this.AddSinglePoint(p, this.nowR); } } blnSet = true; }else { // this.AddSinglePoint(pos, this.nowR); blnSet = false; } } } if (kind == cv.touch_ended){ // this.ResetDrawPoint(); } if (blnSet){ this.lastMousePostion = this.mousePosition; } this.setUpdate(); } AddSinglePoint(pos, r){ this.arrUsedPoint.push(pos); d = new Path(); for(var i=0;i<this.arrUsedPoint.length;i++){ var p = this.arrUsedPoint[i]; if (i==0){ d.moveTo(p.x, p.y); }else{ d.lineTo(p.x, p.y); } } this.showPoints = d; } render() { return ( <View style={styles.container} {...this._panResponder.panHandlers}> <View style={styles.mouseView}> <Surface ref={'lineView'} width={ScreenWidth} height={ScreenHeight}> <Shape d={this.showPoints} stroke={'rgb(0,0,255)'} strokeWidth={this.nowR} /> </Surface> </View> </View> ); } }
这里主要是在AddUsePoint里面对触摸点进行处理,在touchmove之后,每次都要保存好获得到的点,然后取差值,进行计算
上面代码运行后,得到的线条是这样的:
看到结果后,是不是很不理想,我们想要的不是横平竖直啊,怎么使它们变得平滑呢,我开始想的是贝塞尔曲线,于是在网上找,终于找到一个算法,叫B样条曲线算法,其实这个就是贝塞尔的一种,原理大概就是根据其中几个点进行一个公式算法,得到这些点之间的其他点。
于是在上面的代码进行改善,修改AddUsePoint,添加B样条曲线算法,先看看效果:
效果很不错哦~
代码如下:
AddUsePoint(pos, kind){ if (kind == cv.touch_begin){ this.lastMousePostion = this.mousePosition; this.arrOrgPoint.push(pos); this.AddSinglePoint(pos, this.nowR); this.blnCanDraw = true; }else if (this.blnCanDraw){ this.arrOrgPoint.push(pos); var blnSet = false; if (this.arrOrgPoint.length > 2){ var listTemp = [];//将最新的三个点加入一个临时数组里面 listTemp.push(this.arrOrgPoint[this.arrOrgPoint.length - 3]); listTemp.push(this.arrOrgPoint[this.arrOrgPoint.length - 2]); listTemp.push(this.arrOrgPoint[this.arrOrgPoint.length - 1]); listTemp = this.BSpline2Smooth1(listTemp, false);//将数组传入算法中进行计算 for(var i=0;i<listTemp.length;i++){ this.AddSinglePoint(listTemp[i], this.nowR); } if (this.arrUsedPoint.length > 500){//控制点的数量,也就是线的长度。 this.blnCanDraw = false; } blnSet = true; }else{ var count = Utils.DisP(this.lastMousePostion, pos); if (count > 1){ var c = Math.ceil(count); for(var i=0; i < c; i++){ if (i == c - 1){ this.AddSinglePoint(pos, this.nowR); }else{ var p = Utils.LerpP(this.lastMousePostion, pos, (i + 1) / c); this.AddSinglePoint(p, this.nowR); } } blnSet = true; }else { // this.AddSinglePoint(pos, this.nowR); blnSet = false; } } } if (kind == cv.touch_ended){ // this.CompareBihua(); // this.ResetDrawPoint(); } if (blnSet){ this.lastMousePostion = this.mousePosition; } this.drawTouch && this.drawTouch.setPoints(this.showPoints); } BSpline2Smooth1(list, blnSet){//曲线算法处理函数 var aList = []; aList = aList.concat(list); if (blnSet){ aList.unshift(list[0]); aList.push(list[list.length - 1]); } var tList = []; var loc1 = 1; var start = {}, end = {}; while(loc1 < aList.length - 1){ start = aList[loc1 - 1]; end = aList[loc1 + 1]; tList.push(Utils.LerpP(aList[loc1-1], aList[loc1], 0.5));//添加两点的中点 this.BSpline2Smooth2(tList, start, aList[loc1], end);//最主要的是这里 tList.push(Utils.LerpP(aList[loc1], aList[loc1+1], 0.5)); ++loc1; } var rl = Utils.ResampleByLen(tList, 2);//得到处理之后的点之后,对点数组进行标准化处理,就算输出总长度,每个2个单位距离去一个插值点,得到新数据 if (rl != null){ return rl }else{ return tList; } } BSpline2Smooth2(list, arg1, arg2, arg3){ var locx = []; var locy = []; locx.push((arg1.x + arg2.x) * 0.5); locx.push(arg2.x - arg1.x); locx.push((arg1.x - 2*arg2.x + arg3.x) * 0.5); locy.push((arg1.y + arg2.y) * 0.5); locy.push(arg2.y - arg1.y); locy.push((arg1.y - 2*arg2.y + arg3.y) * 0.5); var loc6 = parseInt(Utils.CountDistance(arg1, arg3)); var loc7 = 0; var loc8 = 0; while(loc7 < loc6){ loc8 = loc7 / loc6; var loc5 = { x: locx[0] + loc8 * (locx[1] + locx[2] * loc8), y: locy[0] + loc8 * (locy[1] + locy[2] * loc8) }; list.push(loc5); loc7++; } }
Utils类《-点这里查看,我这里贴出来
相关文章推荐
- React中state和props
- react-native ListView的属性flexWrap为wrap失效解决
- react-native run-android 报错
- The Road to learn React书籍学习笔记(第三章)
- ReactNative学习-滑动查看图片第三方组件react-native-swiper
- 启动react-native run-android找不到文件问题
- ReactNative踩坑日志——使用async/await语法解决网络请求的异步导致的指令执行顺序错乱问题
- 详解React 的几种条件渲染以及选择
- react-native android学习-开发环境(windows10)
- Windows下React-Native开发环境配置
- React Native的初步接触
- Spring Boot与React集成的示例代码
- React学习笔记---创建组件
- React-Redu
- react(二)父子组件间的数据传递---prop
- react-native入门之ListView-安卓开发者的第一视角
- React-Native AsyncStorage存储key管理小技巧
- react-native(五)生成App
- RN(react native)入坑指南-10,组件的生命周期
- react-native run-android 慢