nashaofu / screenshots

A screenshot plugin for electron and react
https://nashaofu.github.io/screenshots/
MIT License
380 stars 96 forks source link

修复绘制画笔、涂鸦、矩形、椭圆等模糊的问题 #245

Open xieerduos opened 4 hours ago

xieerduos commented 4 hours ago

修复canvas画布绘制图形模糊的问题,原因是没有对画布进行缩放

效果对比

左边为不模糊的效果 - 右边为当前效果

image

修改代码1,增加scale缩放比

https://github.com/nashaofu/screenshots/blob/bde35a35bc1876098aa5d00c5c1ad088ab4fe9fb/packages/react-screenshots/src/Screenshots/ScreenshotsCanvas/index.tsx#L69

需要在绘制的时候添加如下代码

   const dpr = window.devicePixelRatio || 1 // 获取设备的像素比
      // 调整 canvas 的尺寸以匹配设备的像素比
      ctx.canvas.width = bounds.width * dpr
      ctx.canvas.height = bounds.height * dpr
      // 缩放 canvas 的绘图上下文,使绘制内容的分辨率与屏幕相匹配
      ctx.scale(dpr, dpr)

修改后完整的代码如下:

    const draw = useCallback(() => {
      if (!bounds || !ctxRef.current) {
        return
      }

      const ctx = ctxRef.current
      const dpr = window.devicePixelRatio || 1 // 获取设备的像素比
      // 调整 canvas 的尺寸以匹配设备的像素比
      ctx.canvas.width = bounds.width * dpr
      ctx.canvas.height = bounds.height * dpr
      // 缩放 canvas 的绘图上下文,使绘制内容的分辨率与屏幕相匹配
      ctx.scale(dpr, dpr)
      // 开启图像平滑
      ctx.imageSmoothingEnabled = true
      ctx.imageSmoothingQuality = 'low'
      // 清除整个画布区域
      ctx.clearRect(0, 0, bounds.width, bounds.height)
      // 绘制历史记录中的每个 item
      history.stack.slice(0, history.index + 1).forEach((item) => {
        if (item.type === HistoryItemType.Source) {
          item.draw(ctx, item)
        }
      })
    }, [bounds, ctxRef, history])

修改代码2

因为上面修改了缩放比,这里也需要同步修改,否则拖拽会出现问题

https://github.com/nashaofu/screenshots/blob/bde35a35bc1876098aa5d00c5c1ad088ab4fe9fb/packages/react-screenshots/src/Screenshots/ScreenshotsOption/index.tsx#L56

    const dpr = window.devicePixelRatio || 1 // 获取设备像素比

    // 对尺寸和坐标进行缩放比调整
    let x = (childrenRect.left + childrenRect.width / 2) * dpr
    let y = (childrenRect.top + childrenRect.height) * dpr

完整的代码如下:

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => {
    if (!open || !operationsRect || !childrenRef.current || !contentRef.current) {
      return
    }

    const childrenRect = childrenRef.current.getBoundingClientRect()
    const contentRect = contentRef.current.getBoundingClientRect()

    let currentPlacement = placement
    const dpr = window.devicePixelRatio || 1 // 获取设备像素比

    // 对尺寸和坐标进行缩放比调整
    let x = (childrenRect.left + childrenRect.width / 2) * dpr
    let y = (childrenRect.top + childrenRect.height) * dpr
    let currentOffsetX = offsetX

    // 如果左右都越界了,就以左边界为准
    if (x + contentRect.width / 2 > operationsRect.x + operationsRect.width) {
      const ox = x
      x = operationsRect.x + operationsRect.width - contentRect.width / 2
      currentOffsetX = ox - x
    }

    // 左边不能超出
    if (x < operationsRect.x + contentRect.width / 2) {
      const ox = x
      x = operationsRect.x + contentRect.width / 2
      currentOffsetX = ox - x
    }

    // 如果上下都越界了,就以上边界为准
    if (y > window.innerHeight - contentRect.height) {
      if (currentPlacement === Placement.Bottom) {
        currentPlacement = Placement.Top
      }
      y = childrenRect.top - contentRect.height
    }

    if (y < 0) {
      if (currentPlacement === Placement.Top) {
        currentPlacement = Placement.Bottom
      }
      y = childrenRect.top + childrenRect.height
    }
    if (currentPlacement !== placement) {
      setPlacement(currentPlacement)
    }
    if (position?.x !== x || position.y !== y) {
      setPosition({
        x,
        y
      })
    }

    if (currentOffsetX !== offsetX) {
      setOffsetX(currentOffsetX)
    }
  })

最后

感谢作者提供的源码,2021年基于该项目代码实现了,截图功能,并对其中的代码进行过优化

现在再次做一个更加优化版本的截图,再次打开项目发现作者已经更新了react代码,非常感谢

nashaofu commented 3 hours ago

辛苦提交一个pr吧