React Native 开发APP_react-native-image-resizer-程序员宅基地

技术标签: react native  

记录一下项目中主要用到的技术点吧~

一.电子签名的显示,文件存储到手机,上传

电子签名用到的组件:react-native-signature-capture

写文件react-native-fs

上传用到的组件react-native-fetch-blob


import React, { Component, Fragment } from "react";
import { StyleSheet, View, TextInput, Text,TouchableOpacity, Image, FlatList, Dimensions,
} from "react-native";
import { common_url, fetchRequest } from "../../utils/request";
import Dialog, { DialogButton, DialogContent, DialogFooter, DialogTitle } from "react-native-popup-dialog";
import SignatureCapture from "react-native-signature-capture";
import RNFetchBlob from "react-native-fetch-blob";
var RNFS = require('react-native-fs');
export default class SignConstract extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible:false,
      contract:"",
      signImg:"",
    };
  }

 
  //签名
  _onSaveEvent(result) {
    if(result.encoded!=undefined){
      this.setState({
        signImg:result.encoded,  //result.encoded base64编码,用于签名图片的显示
      })
    }

     
    var timestamp = (new Date()).getTime();
    const path = RNFS.PicturesDirectoryPath + '/'+timestamp+'signature.png';
      // write the file
      RNFS.writeFile(path, result.encoded, 'base64')
        .then((success) => {
          console.log('存储在手机的文件路径path', path);
        })
        .catch((err) => {
          console.log(err.message);
        });


    //转化后的本地路径
    this.upload(result.pathName)
  }
 //上传文件
  upload(pathName){
    DeviceStorage.get("ownerId").then((ownerId) => {
      var declareId ="1";
      let body = [{
        name: "declareId", data:declareId
      },
        {
          name: "sign",
          filename: "测试",
          type: "image/png",
          data: RNFetchBlob.wrap(pathName)
        }];
  
      RNFetchBlob.fetch("POST", common_url+"hserp_owners/participateSing", {
        // 上传图片要设置Header
        "Content-Type":"multipart/form-data",
      }, body)
        .uploadProgress((written, total) => {
          // 本地查找进度
        })
        .progress((received, total) => {
          let perent = received / total;
          console.log("上传进度打印", perent);
        })
        .then((response) => response.json())
        .then((response) => {
          console.log("上传信息返回", response);
        })
        .catch((error) => {
          // 错误信息
          console.log(error);
        });


    });
  }
  //保存签名
  saveSign() {
    this.refs["sign"].saveImage();
  }
  //清除签名
  resetSign() {
    this.refs["sign"].resetImage();
  }

  render() {
    return (
      <View style={styles.container}>
          <View style={
   { flex: 1 }}>
            <View style={styles.content}>
              <View style={styles.rowBorder}>
              <TouchableOpacity style={styles.rowContent} onPress={() => {
                this.setState({
                  visible: true
                });
              }}>
                <Text style={
   {color:theme.color}}>签名:</Text>
                <Image source={
   { uri: "data:image/jpg;base64," + this.state.signImg }} style={styles.img}/>
              </TouchableOpacity>
            </View>

          </View>
          {/*确认*/}
          <Dialog
            width={0.9}
            height={0.7}
            visible={this.state.visible}
            footer={
              <DialogFooter>
                <DialogButton
                  text="取消"
                  onPress={() => {
                    this.setState({
                      visible: false
                    });
                  }}
                />
                <DialogButton
                  text="确定"
                  onPress={() => {
                    this.setState({
                      visible: false
                    }, () => {
                      this.saveSign();
                    });
                  }}
                />
              </DialogFooter>
            }
            dialogTitle={<DialogTitle title="签名确认"/>}>
            <DialogContent style={
   { flex: 1 }}>
              <View style={
   { flex: 1 }}>
                <SignatureCapture
                  ref="sign"
                  style={
   { flex: 1 }}
                  minStrokeWidth={5}
                  maxStrokeWidth={5}
                  showNativeButtons={false}
                  saveImageFileInExtStorage={true}  //是否存储在手机
                  onSaveEvent={this._onSaveEvent.bind(this)}
                />
              </View>
            </DialogContent>
          </Dialog>
        <View style={styles.btn}>
          <Text style={styles.white}
                onPress={() => {
                  if(!this.state.signImg){
                    this.refs.toast.show("请签名", 4000);
                    return false

                  }else{
                    Actions.Renovation({sign:this.state.path})
                  }

                }}>下一步</Text>
        </View>
      </View>

    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: theme.gray
  },
});

 

二. 图片压缩 

用到的组件:react-native-image-resizer,上传前自己用promise做了个处理压缩多图

import React, { Component } from "react";
import {StyleSheet, View, ScrollView, TextInput, Text, TouchableOpacity, Image, FlatList, Dimensions, DeviceEventEmitter, ImageBackground} from "react-native";
import { common_url, fetchRequest } from "../../utils/request";
import RNFetchBlob from "react-native-fetch-blob";
import ImageResizer from 'react-native-image-resizer';
export default class RepaireApply extends Component {
  constructor(props) {
    super(props);
    this.state = {
      imgArr: [],
      typeArr: [],
      date: "",
      total: "",
      imgId: ""
    };
  }

  componentWillMount() {
    this.getList();
    this.deEmitter = DeviceEventEmitter.addListener("left", (a) => {
      this.setState({
        imgArr: a
      });
    });
  }

  componentWillUnmount() {
    this.deEmitter.remove();
  }

  async save() {
      DeviceStorage.get("ownerId").then(async(ownerId) => {
        let arr = [];
        this.state.imgArr.map((item, index) => {
          arr.push(ImageResizer.createResizedImage(item, 100, 100, "PNG", 100 ))
        })

        let arr2 = [];
        let result=await Promise.all(arr)
        result.map((item, index) => {
          var obj = {
            name: "picture" + index,
            filename: "picture" + item.name,
            type: "image/png",
            data: RNFetchBlob.wrap(item.uri)
          };
          arr2.push(obj);
        });

        arr2.push({
          name: "request", data: this.state.requests
        }, {
          name: "size", data: this.state.imgArr.length + ""
        });
        RNFetchBlob.fetch("POST", common_url + "hserp_owners/repairMaintenance", {
          "Content-Type": "multipart/form-data"
        }, arr2)
          .uploadProgress((written, total) => {
         
          })
          .progress((received, total) => {
           
          })
          .then((response) => response.json())
          .then((response) => {
            
          })
          .catch((error) => {
            // 错误信息
            console.log(error);
          });
      });
  }

 

三. 手势系统运用:动态改变scrollview 的滑动方向

import React, { Component } from "react";
import { StyleSheet,  View,Text, TouchableOpacity,ScrollView, PanResponder} from "react-native";
import { fetchRequest } from "../../utils/request";
var Dimensions = require("Dimensions");
export default class ParkSpace extends Component {
  constructor(props) {
    super(props);
    this.state = {
      horizontal:false
    };
  }

  componentWillMount() {
    
    this._panResponder = PanResponder.create({

      // 要求成为响应者
      // nativeEvent
      // gestureState  dx - 从触摸操作开始时的累计横向路程    dy - 从触摸操作开始时的累计纵向路程


      //表示是否成为滑动事件的劫持者,如果返回是,则不会把滑动事件传递给它的子元素。
      onStartShouldSetPanResponder: (evt, gestureState) => false,

      //表示是否成为事件的劫持者,如果返回是,则不会把事件传递给它的子元素
      onStartShouldSetPanResponderCapture: (evt, gestureState) => false,


      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onStartShouldSetResponderCapture: (evt)=> true,
      VonMoveShouldSetResponderCapture: (evt)=> true,

      //开始手势操作
      onPanResponderGrant: (evt, gestureState) => {
        // this._highlight();
        this.setState({
          horizontal:true
        })
      },


      //触摸点移动
      onPanResponderMove: (evt, gestureState) => {
        this.state.ScreenWidth,gestureState.moveX,)
        console.log(`gestureState.moveX  : ${gestureState.moveX }   gestureState.moveY  : ${gestureState.moveY }`);
        if(gestureState.moveX<this.state.ScreenWidth){
         //动态改变
          this.setState({
            horizontal:true
          })
        }else{
          this.setState({
            horizontal:false
          })
        }
      },
      //用户放开了所有的触摸点,且此时视图已经成为了响应者
      onPanResponderRelease: (evt, gestureState) => {
      },
      //另一个组件已经成为了新的响应者,所以当前手势将被取消
      onPanResponderTerminate: (evt, gestureState) => {
      },
    });
  }

  show(typeId,carType, price,number) {
    Actions.CartFee({"typeId":typeId,"carType": carType, "carPrice": price,"number":number,area:this.state.area });
  }

  render() {
    return (
      <View style={
   {display:"flex",height:"100%"}}>

        <ScrollView style={
   {flex:1}}
                    horizontal={this.state.horizontal} //水平
                    showsHorizontalScrollIndicator={true}
                    showsVerticalScrollIndicator={true}
                    removeClippedSubviews={false}
                    overScrollMode="always">

          <View  style={
   {width:this.state.parkWidth,height:this.state.parkHeight,backgroundColor: "#00ff00"}}
                 {...this._panResponder.panHandlers}>
            {this.state.cars.map((item) => {
              return (
                <TouchableOpacity style={
   { position: "absolute", left: (item.abscissa_y - 1) * this.state.cellWidth, top: (item.abscissa_x - 1) * this.state.cellHeight }}
                                  key={item.id}
                                  onPress={() => {
                                    if (item.state != "3") {
                                      this.refs.toast.show("该车位已租售,请重新选择", 4000
                                      return false;
                                    } else {
                                      this.show(item.type_id[0],item.type_id[1], item.price,item.parking_number);
                                    }
                                  }}
                >
                  <View style={
   { width:60,
                    height:30,
                    backgroundColor: "#848484",
                    borderColor: "#fff",
                    borderBottomWidth:2,
                    borderTopWidth:2,
                    borderLeftWidth:2,
                    transform: [{ rotate: item.angle+"deg"}]
                  }}>
                    <Text style={styles.zhu}>▎</Text>
                    <Text style={styles.zhu}>▎</Text>
                    <Text style={
   {position:"absolute", top:"30%", left:"30%", color:"white", fontSize:8,transform: [{ rotate: item.angle+"deg"}]}}>{item.parking_number}</Text>
                    <Text style={styles.tang}>▲</Text>

                  </View>
                </TouchableOpacity>
              );
            })}
          </View>
        </ScrollView>
        <Toast
          ref="toast"
          style={
   { backgroundColor:theme.toastColor}}
          position='center'
          fadeInDuration={theme.fadeInDuration}
          fadeOutDuration={theme.fadeOutDuration}
          opacity={0.7}
          textStyle={
   { color: "white" }}
        />
      </View>
    );
  }
}
const styles = StyleSheet.create({
});

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Rqlinna/article/details/105960196

智能推荐

医疗器械计算机系统审评准则,CFDA医疗器械技术审评中心发布的医疗器械产品指导原则汇总(截至2017年12月5日).pdf...-程序员宅基地

文章浏览阅读160次。CFDA医疗器械技术审评中心发布的医疗器械产品指导原则汇总(截至2017年12月5日)RAList| 总局发布的医疗器械产品指导原则知多少?(截2017-12-05十二梧桐Hereyou could seethe latest andthewholeproduct registration guidancewhich issuedby CFDAtillnow,hopethat itcopuldhe...

range arange_(0,5)tensor-程序员宅基地

文章浏览阅读1.3k次。这是一个小坑,torch.range 已经被弃用了/torch.range(0,5)__main__:1: UserWarning: torch.range is deprecated in favor of torch.arange and will be removed in 0.5. Note that arange generates values in [start; end), ..._(0,5)tensor

pytest之fixture使用详解-程序员宅基地

文章浏览阅读1.7k次。简介:  fixture区别于unnitest的传统单元测试(setup/teardown)有显著改进:  1.有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活。  2.按模块化的方式实现,每个fixture都可以互相调用。  3.fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function,类cl..._pytest.fixture cannot find

电子科技大学CSDN高校俱乐部:浅谈计算机与数学——ACM总教练杨鹏老师讲座_csdn 杨鹏-程序员宅基地

文章浏览阅读2.6k次。时间:11月13日19:30——21:30主 办: 电子科技大学创新创业中心&数学学院团委承 办: 电子科技大学CSDN高校俱乐部主 题:浅谈计算机与数学——ACM总教练杨鹏老师讲座地 点:基础教学楼A101。嘉 宾:数学学院分团委王老师等听 众: 电子科技大学在校学生等11月13日晚7点30分,在教学楼A区101教室,校ACM队总教练、CS_csdn 杨鹏

win8.1任务栏通知区域已经卸载的软件图标删除(强迫症治疗)_通知栏 已卸载软件 图标删除-程序员宅基地

文章浏览阅读2.2k次。win8.1任务栏通知区域已经卸载的软件图标删除_通知栏 已卸载软件 图标删除

苹果变了:Mac 用自研芯片、iPhone 替代车钥匙-程序员宅基地

文章浏览阅读802次。作者 | 屠敏头图 | CSDN 下载自东方 IC出品 | CSDN(ID:CSDNnews)与往年有所不同,因为一场突如其来的“黑天鹅”事件,今年属于开发者的饕餮盛宴一减再减,如Fa..._mac芯片演变

随便推点

Flash 中与 JS 的通信-程序员宅基地

文章浏览阅读46次。SetVariable 可以很方便的实现多浏览器兼容。举例如下。html 页中的 JavaScript 函数:function GetSwfUrl(){var pics1 = parseInt(Math.random()*5)+1;var pics2 = parseInt(Math.random()*5)+1;document.my_swfId.SetVariable("pic01Num...

Kibana访问权限控制-程序员宅基地

文章浏览阅读788次。ELK平台搭建完成后,由于Kibana的服务也是暴露在外网,且默认是没有访问限制的(外部所有人都可以访问到),这明显不是我们想要的,所以我们需要利用Nginx接管所有Kibana请求,通过Nginx配置将Kibana的访问加上权限控制,简单常见的方式可以使用如下三种方式:方案一:利用Nginx用户认证模块 使用Nginx的用户认证模块(ngx_http_auth_basic_mo..._设置限制ip访问kibana

MSVCR140.dll文件丢失?程序无法运行?解决办法!!!_mvds140-程序员宅基地

文章浏览阅读5w次,点赞3次,收藏4次。这是博主的第一篇博客,写的不好的地方还请见谅!博主某天在玩电脑时无意中点了一个“立即注销”的按钮,在注销的过程中遇到了“你的电脑遇到问题,需要重新启动,我们只收集某些错误信息,然后你可以重新启动!”等到电脑重启之后,网络连接之后,浏览器不能上网,所有应用不是打不开就是没网!博主上网查了注销的意思,以为问题出在了“注销”把应用的注册表信息清空了,想到只有重装系统这_mvds140

使用python绘制热力图(调用百度地图API)_python绘制百度地图热力图-程序员宅基地

文章浏览阅读5.8k次,点赞6次,收藏66次。这里写自定义目录标题*初始数据——地址*获取百度地图ak1.百度地图开放平台——我的应用 [link](http://lbsyun.baidu.com/apiconsole/key#/home)2.申请应用,获取ak*将地图转换为经纬度坐标方案一: [link](https://maplocation.sjfkai.com/)方案二:pythonList item*初始数据——地址可以是任意格式的文本*获取百度地图ak1.百度地图开放平台——我的应用 link2.申请应用,获取ak提_python绘制百度地图热力图

PyTorch 入门实战(四)——利用Torch.nn构建卷积神经网络_import torch.nn as nn-程序员宅基地

文章浏览阅读3.1k次,点赞15次,收藏48次。目录文章目录一、概念二、使用nn.Module创建一个网络框架三、利用PyTorch卷积模块填充网络框架四、自己写一个VGG-16带有BatchNorm层的网络五、总结一、概念需要声明的是构建卷积神经网络需要有一定的面向对象基础,因为所有建立的模型结构都是继承自nn.Module这个基类所完成的我们需要新建一个子类,并且构造函数和前向传播等方法需要被重写才能实现自己编写的网络..._import torch.nn as nn

R 语言 Monte Carlo方法 和平均值法 计算定积分, 考虑随机投点法,计算在置信度0.05, 要求为ϵ=0.01 , 所需要的试验次数_r语言平均值法计算定积分-程序员宅基地

文章浏览阅读1.6k次。蒙特·卡罗方法(MonteCarlomethod),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。,考虑随机投点法,计算在置信度0.05,要求为ϵ=0.01,所需要的试验次数。用MonteCarlo方法计算定积分。..._r语言平均值法计算定积分

推荐文章

热门文章

相关标签