当前位置: 代码网 > it编程>前端脚本>Node.js > node文件资源管理器的图片预览从零实现

node文件资源管理器的图片预览从零实现

2024年05月19日 Node.js 我要评论
使用技术使用 next.js 的 image 组件显示图片。自带图片压缩生成快速预览的 webp 格式图片使用 antd 的 previewgroup 组件实现原图浏览,自带缩小、放大、上一张、下一张

 使用技术

  • 使用 next.js 的 image 组件显示图片。自带图片压缩生成快速预览的 webp 格式图片
  • 使用 antd 的 previewgroup 组件实现原图浏览,自带缩小、放大、上一张、下一张等功能

功能实现

文件树

explorer/src/app/path/[[...path]]/card-display.tsx
explorer/src/app/path/[[...path]]/page.tsx
explorer/src/components/preview/ext-rxp.tsx
explorer/src/components/preview/index.tsx
explorer/src/components/preview/proview-group-context.tsx
explorer/src/components/use-replace-pathname.ts

文件路径:explorer/src/components/preview/ext-rxp.tsx

一些判断文件后缀名方法

export const imgrxp = /\.(jpg|jpeg|gif|png|webp|ico)$/i
const rawrxp = /\.(cr2|arw)/i
const gifrxp = /\.(gif)$/i
const ziprxp = /\.(zip|rar|7z|tar\.xz|tar)(\.+\d+)?$/i
const videorxp = /\.(mp4|mkv|mov|wmv|avi|avchd|flv|f4v|swf)(\.+\d+)?$/i
export const israw = (path: string) => rawrxp.test(path)
export const isimage = (path: string) => imgrxp.test(path)
export const isgif = (path: string) => gifrxp.test(path)
export const iszip = (path: string) => ziprxp.test(path)
export const isvideo = (path: string) => videorxp.test(path)

文件路径:explorer/src/components/preview/index.tsx

预览封装组件,根据是否为文件夹、视频、图片、压缩包显示不同的 icon。

点击图片时,使用 antd 的 previewgroup 组件查看原图。

import react from 'react'
import { fileoutlined, filezipoutlined, folderoutlined, videocameraoutlined } from '@ant-design/icons'
import image from 'next/image'
import { isgif, isimage, isvideo, iszip } from '@/components/preview/ext-rxp'
import { usepreviewgroupdispatch } from '@/components/preview/proview-group-context'
import { readdiritemtype } from '@/explorer-manager/src/type'
import { usereplacepathname } from '@/components/use-replace-pathname'
const preview: react.fc<{ item: readdiritemtype }> = ({ item }) => {
  const previewgroupdispatch = usepreviewgroupdispatch()
  const { name, is_directory } = item
  const { staticpath, joinsearchpath } = usereplacepathname()
  if (is_directory) {
    return <folderoutlined />
  }
  if (isvideo(name)) {
    return <videocameraoutlined />
  }
  if (isimage(name)) {
    const image_path = staticpath(name)
    return (
      <image
        onclick={() => previewgroupdispatch(name)}
        src={image_path}
        alt={name}
        fill
        sizes="375px"
        style={{
          objectfit: 'scale-down', //"contain" | "cover" | "fill" | "none" | "scale-down"
        }}
        unoptimized={isgif(image_path)}
        placeholder="empty"
      />
    )
  }
  if (iszip(name)) {
    return <filezipoutlined />
  }
  return <fileoutlined />
}
export default preview

文件路径:explorer/src/components/preview/proview-group-context.tsx

antd previewgroup 组件封装。

需要在顶层目录插入 previewgroupprovider 上下文组件,导出 usepreviewgroup、usepreviewgroupdispatch 读写方法。

'use client'
import react from 'react'
import { image as antdimage } from 'antd'
import { findindex } from 'lodash'
import { isimage } from '@/components/preview/ext-rxp'
import { usereplacepathname } from '@/components/use-replace-pathname'
import createctx from '@/lib/create-ctx'
import { usereaddircontext } from '@/app/path/readdir-context'
export const previewgroupcontent = createctx<string>()
export const usepreviewgroup = previewgroupcontent.usestore
export const usepreviewgroupdispatch = previewgroupcontent.usedispatch
const antdimagepreviewgroup: react.fc<react.propswithchildren> = ({ children }) => {
  const { staticpath } = usereplacepathname()
  const readdir_list = usereaddircontext()
  const image_list = readdir_list.filter((item) => isimage(item.name))
  const name = usepreviewgroup()
  const previewgroupdispatch = usepreviewgroupdispatch()
  return (
    <antdimage.previewgroup
      preview={{
        visible: !!name,
        current: findindex(image_list, { name }),
        onvisiblechange: () => {
          previewgroupdispatch('')
        },
        onchange: (current) => {
          previewgroupdispatch(image_list[current].name)
        },
      }}
      items={image_list.map(({ name }) => staticpath(name))}
    >
      {children}
    </antdimage.previewgroup>
  )
}
const previewgroupprovider: react.fc<{ children: react.reactnode }> = ({ children }) => {
  return (
    <previewgroupcontent.contextprovider value={''}>
      <antdimagepreviewgroup>{children}</antdimagepreviewgroup>
    </previewgroupcontent.contextprovider>
  )
}
export default previewgroupprovider

文件路径:explorer/src/components/use-replace-pathname.ts

添加一个获取不同路径的hooks

  • replace\_pathname 将不需要的一级路径 /path/ 过滤掉
  • joinsearchpath 拼接过滤掉 /path/ 的 pathname
  • joinpath 拼接未过滤的 pathname
  • staticpath 拼接得到获取文件地址
import { usepathname } from 'next/navigation'
export const pathexp = /(^\/)?path/
export const encodepathitem = (path: string) => {
  return path
    .split('/')
    .map((text) => encodeuricomponent(text))
    .join('/')
}
export const usereplacepathname = () => {
  const pathname = decodeuricomponent(usepathname() || '')
  const replace_pathname = pathname.replace(pathexp, '')
  const joinsearchpath = (path: string) => encodepathitem(`${replace_pathname}/${path}`)
  const joinpath = (path: string) => encodepathitem(`${pathname}/${path}`)
  const staticpath = (path: string) => `/static${joinsearchpath(path)}`
  return {
    pathname: pathname,
    replace_pathname: replace_pathname,
    joinsearchpath: joinsearchpath,
    joinpath: joinpath,
    staticpath: staticpath,
  }
}

文件路径:explorer/src/app/path/[[...path]]/card-display.tsx

将 preview 组件插入 list item 内

...
import preview from '@/components/preview'
const carddisplay: react.fc = () => {
  const pathname = usepathname()
  const readdir = usereaddircontext()
  const column = usecardcolumncontext()
  return (
    <list
...
                  <div style={{ position: 'absolute', width: '100%', height: '100%' }}>
                    <preview item={item} />
                  </div>
...

文件路径:explorer/src/app/path/[[...path]]/page.tsx

将 previewgroupprovider 组件插入最顶部

...
import previewgroupprovider from '@/components/preview/proview-group-context'
const page: react.fc = () => {
  const display_type = usedisplaytypecontext()
  return <previewgroupprovider>{display_type === 'table' ? <tabledisplay /> : <carddisplay />}</previewgroupprovider>
}
export default page

效果

git-repo

yangws29/share-explorer

以上就是node文件资源管理器的图片预览从零实现的详细内容,更多关于node文件图片预览的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com