当前位置: 首页 > 工具软件 > Remax > 使用案例 >

(记)在remax,小程序中画布的使用

谢豪
2023-12-01

demo1

import * as React from 'react';
import { View, Button, Canvas, Image } from 'remax/wechat';
import { authorize, saveImageToPhotosAlbum, getSetting, showToast, getImageInfo, openSetting, canvasToTempFilePath, createCanvasContext, reLaunch, showLoading } from 'remax/wechat';
import { getCompanyId } from '../../../api/company'
import { postActivityListMiniCode } from '../../../api/activity'
import { useQuery } from 'remax';
export default () => {
  const query = useQuery();
  const [openStatus, setopenStatus] = React.useState(true);
  const [Imgurl, setImgUrl] = React.useState({});
  const [saveShare, setSaveShare] = React.useState(false);
  const [codeImg, setCodeImg] = React.useState('')
  // 保存图片
  const saveShareImg = () => {
    const { companyId, activityId } = query
    // 获取用户是否开启用户授权相册
    if (!openStatus) {
      openSetting({
        success: (result) => {
          if (result) {
            if (result.authSetting["scope.writePhotosAlbum"] === true) {
              setopenStatus(true);
              saveImageToPhotosAlbum({
                filePath: Imgurl.tempFilePath,
                success () {
                  showToast({
                    title: '图片保存成功',
                    icon: 'none',
                    duration: 2000
                  })
                  setSaveShare(true)
                  setTimeout(() => {
                    reLaunch({
                      url: `/pages/home/activities/index?id=${companyId}&activityId=${activityId}`,
                    })
                  }, 500);
                },
                fail () {
                  showToast({
                    title: '保存失败',
                    icon: 'none'
                  })
                }
              })
            }
          }
        },
        fail: () => { },
        complete: () => { }
      });
    } else {
      getSetting({
        success (res) {
          // 如果没有则获取授权
          if (!res.authSetting['scope.writePhotosAlbum']) {
            authorize({
              scope: 'scope.writePhotosAlbum',
              success () {
                setopenStatus(true)
                saveImageToPhotosAlbum({
                  filePath: Imgurl.tempFilePath,
                  success () {
                    showToast({
                      title: '图片保存成功',
                      icon: 'none',
                      duration: 2000
                    })
                    setSaveShare(true)
                    setTimeout(() => {
                      reLaunch({
                        url: `/pages/home/activities/index?id=${companyId}&activityId=${activityId}`,
                      })
                    }, 500);
                  },
                  fail () {
                    showToast({
                      title: '保存失败',
                      icon: 'none'
                    })
                  }
                })
              },
              fail () {
                // 如果用户拒绝过或没有授权,则再次打开授权窗口
                setopenStatus(false)
                showToast({
                  title: '请设置允许访问相册',
                  icon: 'none'
                })
              }
            })
          } else {
            setopenStatus(true)
            saveImageToPhotosAlbum({
              filePath: Imgurl.tempFilePath,
              success () {
                showToast({
                  title: '图片保存成功',
                  icon: 'none',
                  duration: 2000
                })
                setSaveShare(true)
                setTimeout(() => {
                  reLaunch({
                    url: `/pages/home/activities/index?id=${companyId}&activityId=${activityId}`,
                  })
                }, 500);
              },
              fail () {
                showToast({
                  title: '保存失败',
                  icon: 'none'
                })
              }
            })
          }
        },
        fail (err) {
          console.log(err)
        }
      })
    }
  };
  // 开始绘制
  const drawGoodsPoster = (companyUrl, url) => {
    const ctx = createCanvasContext('shareImg')
    let bgImg = 'https://static.chexx01.cn/images/omc/2901ccce-4bcc-4077-891e-3c0c5f14b17b.png'
    showLoading({ title: '生成中...', icon: 'none' }).catch();
    getImageInfo({
      src: bgImg,
      success (res) {
        const img_width = res.width
        const img_height = res.height
        let bgPicturePath = res.path
        ctx.drawImage(bgPicturePath, 0, 0, img_width, img_height);
        ctx.draw(true);
        drawUser(companyUrl, ctx)
        drawCode(url, ctx)
        setTimeout(() => {
          canvasToTempFilePath({
            x: 0,
            y: 0,
            width: 548,
            height: 920,
            destWidth: 548,
            destHeight: 920,
            canvasId: 'shareImg',
            success: function (res) {
              const data = res
              setImgUrl({ ...data })
              showToast({
                title: '生成成功',
              })
            },
            fail: function () {
              showToast({
                title: '生成失败',
                icon: 'none'
              })
            },
          })
        }, 2000)
      }
    })
  }
  // 公司头像
  const drawUser = (companyUrl, ctx) => {
    getImageInfo({
      src: companyUrl,
      success (res) {
        ctx.save()
        const avatarurl_width = 130;
        const avatarurl_heigth = 130;
        const avatarurl_x = 211;
        const avatarurl_y = 389;
        ctx.beginPath();
        ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
        ctx.clip();
        ctx.drawImage(res.path, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth);
        ctx.restore();
        ctx.draw(true);
      }
    })
  }
  // 二维码
  const drawCode = (url, ctx) => {
    console.log(url, 'url');
    getImageInfo({
      src: url,
      success (res) {
        console.log(res, '进啦了');
        ctx.save()
        const avatarurl_width = 220;
        const avatarurl_heigth = 220;
        const avatarurl_x = 163.5;
        const avatarurl_y = 680;
        ctx.beginPath();
        ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
        ctx.clip();
        ctx.drawImage(res.path, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth);
        ctx.restore();
        ctx.draw(true);
      }
    })
  }
  React.useEffect(() => {
    const { scene, companyId, activityId } = query
    if (scene) {
      let sceneData = decodeURIComponent(scene)
      let id = sceneData.split('&')[0].split('=')[1]
      let activityId = sceneData.split('&')[1].split('=')[1]
      let codeData = {
        page_path: '/packageA/pages/home/activities/index',
        activity_id: activityId,
        company_id: id
      }
      console.log(codeData)
      postActivityListMiniCode(codeData).then(res => {
        const { url } = res.data
        setCodeImg(url)
        getCompanyId({ id: companyId }).then(res => {
          const { cover } = res.data
          drawGoodsPoster(cover[0].url, url)
        })
      })
    } else {
      let codeData = {
        // 活动路径
        page_path: 'pages/home/activities/index',
        activity_id: activityId,
        company_id: companyId,
        is_hyaline: true
      }
      console.log(codeData)
      postActivityListMiniCode(codeData).then(res => {
        const { url } = res.data
        console.log(url);
        setCodeImg(url)
        getCompanyId({ id: companyId }).then(res => {
          const { cover } = res.data
          drawGoodsPoster(cover[0].url, url)
        })
      })
    }
  }, [query])

  return (
    <View style={'width: 100vw;height: 100vh;overflow: hidden;background: rgba(0, 0, 0, 0.8);'}>
      <View style={'width:100%;height:80%;margin: 35px 0;text-align: center;'}>
        <Image src={Imgurl.tempFilePath ? Imgurl.tempFilePath : ''} style={'height:100%;width:80%;border-radius: 5PX;'} />
      </View>
      <Canvas canvasId={'shareImg'} style={'width:548px;height:920px;position: absolute;top:-1000px'}>
      </Canvas>
      <Button onClick={() => {
        saveShareImg();
      }} style={saveShare ? 'left:10px;background: #ff9d02;color: #fff;width:95%;position: fixed;bottom: 10px' : 'left:10px;background: #ff9d02;color: #fff;width:95%;position: fixed;bottom: 10px'} disabled={saveShare}>保存到手机</Button>
    </View>
  )
}

demo2

import * as React from 'react';
import { View, Button, Canvas, Image } from 'remax/wechat';
import { authorize, saveImageToPhotosAlbum, getSetting, showToast, getImageInfo, downloadFile, openSetting, canvasToTempFilePath, createCanvasContext } from 'remax/wechat';
import { useQuery } from 'remax';
import red_img from './image/red.png';
import black_img from './image/black.png';
import styles from './index.less';
import Loading from '../Loading/index'
import { getHubDetail, getHubCreateMiniCode } from '../../api/hub'
export default (props) => {
  const canvas_width = 1080;
  const canvas_height = 487;
  const car_height = 754
  const black_height = 149
  const red_width = 596
  const red_height = 177
  const bottom_height = 579
  const core_width = 249
  const core_height = 249
  const red = red_img
  const black = black_img
  const [openStatus, setopenStatus] = React.useState(true);
  const [saveShare, setSaveShare] = React.useState(false);
  const [firstShow, setFirstShow] = React.useState(false);
  const [LoadingShow, seLoadingShow] = React.useState(false);
  const [Imgurl, setImgUrl] = React.useState({});
  const [MiniCode, setMiniCode] = React.useState({})
  const [detail, setDetail] = React.useState({});
  const OriginalPrice = (ctx) => {
    getImageInfo({
      src: black,
      success (res) {
        const img_width = res.width
        const img_height = res.height
        var clip_left, clip_top,
          clip_width, clip_height;

        clip_height = img_width * (black_height / canvas_width);
        if (clip_height > img_height) {
          clip_height = img_height;
          clip_width = clip_height * (canvas_width / black_height);
          clip_left = (img_width - clip_width) / 2;
          clip_top = 0;
        } else {
          clip_left = 0;
          clip_top = (img_height - clip_height) / 2;
          clip_width = img_width
        }
        ctx.drawImage(black, clip_left, clip_top, clip_width, clip_height, 0, 1232, canvas_width, black_height);
        ctx.setFontSize(50)
        ctx.setFillStyle("#fff")
        ctx.fillText(`出厂价:${detail.car_param.price}万`, 70, 1320)
        //线条
        ctx.setStrokeStyle('#fff')
        ctx.beginPath()
        //加粗
        ctx.setLineCap('butt')
        ctx.setLineWidth(4)
        ctx.moveTo(60, 1305)
        ctx.lineTo(485, 1305)
        ctx.stroke()
        ctx.draw(true);
      }
    })
  }
  const price = (ctx) => {
    getImageInfo({
      src: red,
      success (res) {
        const img_width = res.width
        const img_height = res.height
        var clip_left, clip_top,
          clip_width, clip_height;

        clip_height = img_width * (red_height / red_width);
        if (clip_height > img_height) {
          clip_height = img_height;
          clip_width = clip_height * (red_width / red_height);
          clip_left = (img_width - clip_width) / 2;
          clip_top = 0;
        } else {
          clip_left = 0;
          clip_top = (img_height - clip_height) / 2;
          clip_width = img_width
        }
        ctx.drawImage(red, clip_left, clip_top, clip_width, clip_height, 484, 1195, red_width, red_height);
        ctx.setFontSize(100)
        ctx.setFillStyle("#fff")
        ctx.fillText(`${detail.price}万`, 670, 1320)
        ctx.draw(true)
      }
    })
  }
  const titleUser = (ctx) => {
    ctx.setFontSize(55)
    ctx.setFillStyle("#fff")
    ctx.fillText(`${detail.sales_info.username}`, 365, 201)
    const bg_x = 360
    const bg_y = 320
    const bg_w = 200
    const bg_h = 60
    const bg_r = 30
    ctx.save()
    ctx.beginPath()
    ctx.arc(bg_x + bg_r, bg_y + bg_r, bg_r, Math.PI, Math.PI * 1.5)
    ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_r, bg_r, Math.PI * 1.5, Math.PI * 2)
    ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_h - bg_r, bg_r, 0, Math.PI * 0.5)
    ctx.arc(bg_x + bg_r, bg_y + bg_h - bg_r, bg_r, Math.PI * 0.5, Math.PI)
    ctx.clip()
    ctx.fillStyle = '#fff'
    ctx.fillRect(bg_x, bg_y, bg_w, bg_h)
    ctx.restore()
    ctx.setFillStyle("#0078FF")
    ctx.font = 'normal bold 40px sans-serif';
    ctx.fillText('销售顾问', 375, 365)
    ctx.setFillStyle("#fff")
    ctx.draw(true)
    ctx.setFontSize(46)
    ctx.fillText(`${detail.sales_info.mobile}`, 365, 285)
  }
  const avatarUser = (ctx) => {
    downloadFile({
      url: detail.sales_info.avatar,
      success: function (res) {
        ctx.save()
        const avatarurl_width = 260;
        const avatarurl_heigth = 260;
        const avatarurl_x = 59;
        const avatarurl_y = 137;
        ctx.beginPath();
        ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
        ctx.clip();
        ctx.drawImage(res.tempFilePath, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth);
        ctx.restore();
        ctx.draw(true);
      }
    })
  }
  const carCompany = (ctx) => {
    downloadFile({
      url: detail.cover,
      success (res) {
        const img_width = res.width
        const img_height = res.height;
        var clip_left, clip_top,
          clip_width, clip_height;

        clip_height = img_width * (car_height / canvas_width);
        if (clip_height > img_height) {
          clip_height = img_height;
          clip_width = clip_height * (canvas_width / car_height);
          clip_left = (img_width - clip_width) / 2;
          clip_top = 0;
        } else {
          clip_left = 0;
          clip_top = (img_height - clip_height) / 2;
          clip_width = img_width
        }
        ctx.drawImage(res.tempFilePath, clip_left, clip_top, clip_width, clip_height, 0, 487, canvas_width, car_height);
        ctx.draw(true);
        price(ctx)
      }
    })
  }
  const miniCode = (ctx) => {
    downloadFile({
      url: MiniCode.url,
      success (res) {
        const bg_x = 750
        const bg_y = 1600
        const bg_w = core_width
        const bg_h = core_height
        const bg_r = 10
        ctx.save()
        ctx.beginPath()
        ctx.arc(bg_x + bg_r, bg_y + bg_r, bg_r, Math.PI, Math.PI * 1.5)
        ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_r, bg_r, Math.PI * 1.5, Math.PI * 2)
        ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_h - bg_r, bg_r, 0, Math.PI * 0.5)
        ctx.arc(bg_x + bg_r, bg_y + bg_h - bg_r, bg_r, Math.PI * 0.5, Math.PI)
        ctx.clip()
        ctx.drawImage(res.tempFilePath, bg_x, bg_y, bg_w, bg_h)
        ctx.restore()
        ctx.draw(true);
      }
    })
  }
  const topImg = (ctx) => {
    getImageInfo({
      src: 'https://static.chexx01.cn/image/qrcode/top.png',
      success (res) {
        const img_width = res.width
        const img_height = res.height
        var clip_left, clip_top,
          clip_width, clip_height;

        clip_height = img_width * (canvas_height / canvas_width);
        if (clip_height > img_height) {
          clip_height = img_height;
          clip_width = clip_height * (canvas_width / canvas_height);
          clip_left = (img_width - clip_width) / 2;
          clip_top = 0;
        } else {
          clip_left = 0;
          clip_top = (img_height - clip_height) / 2;
          clip_width = img_width
        }
        ctx.drawImage(res.path, clip_left, clip_top, clip_width, clip_height, 0, 0, canvas_width, canvas_height);
        titleUser(ctx)
        //用户头像
        avatarUser(ctx)
        ctx.draw(true);
      }
    })
  }
  const bottomImg = (ctx) => {
    getImageInfo({
      src: 'https://static.chexx01.cn/image/qrcode/bottom.png',
      success (res) {
        const img_width = res.width
        const img_height = res.height
        var clip_left, clip_top,
          clip_width, clip_height;

        clip_height = img_width * (bottom_height / canvas_width);
        if (clip_height > img_height) {
          clip_height = img_height;
          clip_width = clip_height * (canvas_width / bottom_height);
          clip_left = (img_width - clip_width) / 2;
          clip_top = 0;
        } else {
          clip_left = 0;
          clip_top = (img_height - clip_height) / 2;
          clip_width = img_width
        }
        ctx.drawImage(res.path, clip_left, clip_top, clip_width, clip_height, 0, 1360, canvas_width, bottom_height);
        ctx.setFontSize(60)
        ctx.setFillStyle("#fff")
        ctx.fillText('基本信息', 62, 1455)
        ctx.setFontSize(45)
        ctx.fillText(`${detail.title}`, 62, 1550)
        ctx.fillText(`${detail.take_year.slice(0, 4)}年/${detail.mileage}万公里/${detail.emission_standards}`, 62, 1620)
        ctx.draw(true);
        //小程序
        miniCode(ctx)
      }
    })
  }
  const saveShareImg = () => {
    // 获取用户是否开启用户授权相册
    if (!openStatus) {
      openSetting({
        success: (result) => {
          if (result) {
            if (result.authSetting["scope.writePhotosAlbum"] === true) {
              setopenStatus(true);
              saveImageToPhotosAlbum({
                filePath: Imgurl.tempFilePath,
                success () {
                  showToast({
                    title: '图片保存成功',
                    icon: 'none',
                    duration: 2000
                  })
                  setSaveShare(true)
                },
                fail () {
                  showToast({
                    title: '保存失败',
                    icon: 'none'
                  })
                }
              })
            }
          }
        },
        fail: () => { },
        complete: () => { }
      });
    } else {
      getSetting({
        success (res) {
          // 如果没有则获取授权
          if (!res.authSetting['scope.writePhotosAlbum']) {
            authorize({
              scope: 'scope.writePhotosAlbum',
              success () {
                setopenStatus(true)
                saveImageToPhotosAlbum({
                  filePath: Imgurl.tempFilePath,
                  success () {
                    showToast({
                      title: '图片保存成功',
                      icon: 'none',
                      duration: 2000
                    })
                    setSaveShare(true)
                  },
                  fail () {
                    showToast({
                      title: '保存失败',
                      icon: 'none'
                    })
                  }
                })
              },
              fail () {
                // 如果用户拒绝过或没有授权,则再次打开授权窗口
                setopenStatus(false)
                showToast({
                  title: '请设置允许访问相册',
                  icon: 'none'
                })
              }
            })
          } else {
            setopenStatus(true)
            saveImageToPhotosAlbum({
              filePath: Imgurl.tempFilePath,
              success () {
                showToast({
                  title: '图片保存成功',
                  icon: 'none',
                  duration: 2000
                })
                setSaveShare(true)
              },
              fail () {
                showToast({
                  title: '保存失败',
                  icon: 'none'
                })
              }
            })
          }
        },
        fail (err) {
          console.log(err)
        }
      })
    }
  };

  const query = useQuery();
  const { detailId } = query;
  React.useEffect(() => {
    getHubDetail({ id: detailId }).then(res => {
      if (res.status === 200) {
        const { sales_info } = res.data
        sales_info.mobile = `${sales_info.mobile.slice(0, 3)}****${sales_info.mobile.slice(7, 11)}`
        res.data.sales_info = sales_info
        const data = res.data
        setDetail({ ...data })
      }
    });
    getHubCreateMiniCode({
      mini_type: 'customer',
      detail_type: 'hub',
      detail_id: parseInt(detailId)
    }).then((res) => {
      if (res.status === 200) {
        const data = res.data
        setMiniCode({ ...data })
      }
    })
  }, [query]);
  const made = () => {
    setFirstShow(true)
    if (Object.keys(detail).length !== 0 && Object.keys(MiniCode).length !== 0) {
      seLoadingShow(true)
      const ctx = createCanvasContext('shareImg');
      showToast({
        title: '绘制中...',
        icon: 'none'
      })
      //底部
      bottomImg(ctx)
      topImg(ctx)
      //底部
      bottomImg(ctx)
      //原价
      OriginalPrice(ctx)
      //车
      carCompany(ctx)
      avatarUser(ctx)
      //小程序
      miniCode(ctx)
      setTimeout(() => {
        canvasToTempFilePath({
          x: 0,
          y: 0,
          width: 1080,
          height: 1939,
          destWidth: 1080,
          destHeight: 1939,
          canvasId: 'shareImg',
          success: function (res) {
            seLoadingShow(false)
            const data = res
            setImgUrl({ ...data })
            showToast({
              title: '绘制成功',
            })
          },
          fail: function () {
            seLoadingShow(false)
            showToast({
              title: '绘制失败',
              icon: 'none'
            })
          },
        })
      }, 2000)
    } else {
      showToast({
        title: '网络错误请重试',
        icon: 'none'
      })
    }
  };
  return (
    <View style={'width: 100vw;height: 100vh;overflow: hidden;'}>
      {
        firstShow ?
          <View style={'width:100%;height:80%;margin: 10px 0;text-align: center;'}>
            {
              LoadingShow ? <Loading />
                :
                <Image src={Imgurl.tempFilePath ? Imgurl.tempFilePath : ''} style={'height:100%;width:80%;border-radius: 5PX;'} />
            }
          </View> : <View style={'height:80%;margin: 10px 0;color: #808695;display: flex;justify-content: center;align-items: center;'}>
            请点击下面,生成分享图
          </View>
      }
      <View style={'border-top: 1PX solid #E7E7E7;width:100%;text-align: center;margin-top:13%'}>
        {
          Imgurl.tempFilePath ?
            <Button onClick={() => {
              saveShareImg();
            }} style={saveShare ? 'background: #808695;color: #fff; width:95%;left:10px; position: fixed;bottom: 10px' : 'left:10px;background: #0078ff;color: #fff;width:95%;position: fixed;bottom: 10px'} disabled={saveShare}>保存到手机</Button>
            :
            <Button onClick={() => {
              made();
            }} style={'background: #0078ff;color: #fff;width:95%;left:10px;position: fixed;bottom: 10px;'}>生成分享图片</Button>
        }
      </View>
      <Canvas canvasId={'shareImg'} style={'width:1080px;height:2000px;position: absolute;top:-3000px'} />
    </View >
  );
}


 类似资料: