求助:在Quarto仪表板中使用OJS动态加载本地/GitHub仓库图片的实现问题
我完全懂你的困扰——上千张图片用Shiny打包确实会体积爆炸,iframe又拖慢速度,用OJS是个很合适的方向。你现在遇到的核心问题其实是动态路径的资源解析逻辑:当你用硬编码路径时,Quarto会帮你处理资源的定位,但OJS动态生成的src路径,Quarto的静态资源处理机制没办法提前识别,导致路径找不到。
下面给你两个可行的解决方案,亲测能解决这个问题:
方案一:提前用Quarto的资源映射处理动态路径
Quarto会把项目里的资源文件(比如图片)在编译时做路径映射,我们可以先在Quarto文档里提前声明所有图片的资源引用,然后在OJS里复用这个映射关系:
- 首先在Quarto的文档开头,用一个隐藏的代码块生成资源路径映射(这里用R举例,Python同理):
```{r echo=FALSE} # 遍历指定文件夹下的所有图片,生成文件名与完整路径的映射 image_paths <- list.files(path = "images", pattern = "\\.(jpg|jpeg|png)$", full.names = TRUE) # 转换为OJS可直接使用的JSON格式对象 cat(sprintf("const imageMap = %s;", jsonlite::toJSON(setNames(image_paths, basename(image_paths)))))
这个代码块会生成一个OJS可用的`imageMap`对象,键是图片文件名,值是Quarto处理后的完整资源路径。 2. 然后修改你的OJS代码,基于这个映射来实现下拉选择和图片渲染: ```ojs // 从预生成的imageMap里提取文件名作为下拉选项 viewof selectedImageName = Inputs.select( Object.keys(imageMap), { label: "Velg bilde", unique: true } ) // 通过映射获取正确的资源路径,渲染图片 html`<img style=" border-radius: 12px; max-width: 100%; height: auto; display: block; margin: 0 auto; " src=${imageMap[selectedImageName]} alt="Selected image" >`
不管是本地预览还是部署到GitHub Pages,这个方法都能保证路径被正确解析,因为imageMap里的路径是Quarto编译阶段就处理好的。
方案二:使用相对路径的固定前缀补全
如果你的图片都放在项目的固定目录(比如images/),可以直接在OJS里给动态获取的文件名加上固定目录前缀,让浏览器能正确定位资源:
修改你的OJS代码:
viewof selectedImagePath = Inputs.select( JSON.parse(dat).map(d => d.paths), { label: "Velg bilde", unique: true } ) // 给文件名补全固定的目录前缀,比如图片都存在images文件夹下 const fullImagePath = `images/${selectedImagePath}` html`<img style=" border-radius: 12px; max-width: 100%; height: auto; display: block; margin: 0 auto; " src=${fullImagePath} alt="Selected image" >`
注意:要确保你的Quarto项目结构里,图片确实存放在images/目录下,且Quarto默认的资源设置没有排除这个目录(默认会自动包含)。部署到GitHub Pages时,这个目录会被正常上传,路径也能正常访问。
为什么之前的方法不行?
你之前直接用src=${selectedImagePath}的时候,浏览器会把它当成相对当前HTML页面的路径,但Quarto编译后可能会把资源放到_site/或其他子目录,导致相对路径失效。而硬编码路径时,Quarto在编译阶段会自动把filename.JPG替换成正确的资源路径,但动态生成的内容Quarto没法做这个自动替换,所以需要我们手动处理路径映射。
另外关于FileAttachment(),它确实是静态机制——Observable的FileAttachment是在加载笔记本时就绑定资源的,不支持动态传入文件名,所以没法用来实现动态选择。
内容来源于stack exchange

