【问题标题】:ToastUI Image Editor loadImageFromURL doesn't workToastUI 图像编辑器 loadImageFromURL 不起作用
【发布时间】:2019-06-06 21:38:26
【问题描述】:

请注意,这是一个自我回答的问题。

这个问题是关于 ToastUI Image Editor v3.3.0,但它也可能适用于较新的版本。

当您使用this official example 加载图像时:

// Create image editor
var imageEditor = new tui.component.ImageEditor('#my-image-editor canvas', {
    cssMaxWidth: 1000, // Component default value: 1000
    cssMaxHeight: 800  // Component default value: 800
});

// Load image
imageEditor.loadImageFromURL('img/sampleImage.jpg', 'My sample image')

编辑器不会加载图像。该函数既不抛出也不返回任何指示失败的内容,并且您不会收到任何错误消息。它返回一个按照文档中指定的方式解析的承诺。

它仅通过在初始配置中指定来加载图像,之后您无法更改它:

// Create image editor
var imageEditor = new tui.component.ImageEditor('#my-image-editor canvas', {
     includeUI: {
         loadImage: {
             path: 'img/sampleImage.jpg',
             name: 'My sample image'
         },
     },
    cssMaxWidth: 1000, // Component default value: 1000
    cssMaxHeight: 800  // Component default value: 800
});

似乎loadImageFromURL 功能已损坏,据其他用户loadImageFromFile 有同样的问题。

关于这个的问题已经在 GitHub 上提出过,但基本上都被忽略了。现在已经一个月了,不幸的是它仍然没有修复。

所以问题是在这个问题存在的情况下如何欺骗图像编辑器工作。

这是一个表明它不起作用的小提琴:https://fiddle.sencha.com/#view/editor&fiddle/2org

【问题讨论】:

    标签: javascript toast-ui-image-editor


    【解决方案1】:

    TL;DR:
    这是一个工作小提琴:https://fiddle.sencha.com/#view/editor&fiddle/2p0o


    长版:

    有四个问题:

    • 您需要加载初始图像,否则无法使用编辑控件。
    • 您需要等到图像编辑器对象准备好后再调用loadImageFromURL,否则您可能会收到错误或静默失败
    • 加载图片时需要告诉图片编辑器新的尺寸,否则图片会被隐藏或尺寸不正确。
    • 如果您加载外部图片,外部服务器必须设置Access-Control-Allow-Origin 标头并明确允许您的域访问它,否则图片编辑器无法访问它。

    第一个问题可以通过像这样加载空白图像来解决:

    var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
        includeUI: {
            loadImage: {
                path: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
                name: 'Blank'
            },
            theme: whiteTheme,
            menuBarPosition: 'bottom'
        },
        cssMaxWidth: 700,
        cssMaxHeight: 700
    });
    

    第二个问题可以通过等待图像编辑器使用未记录的功能退出其锁定状态来解决。您可以像这样在运行时修补您的loadImageFromURL

    imageEditor.loadImageFromURL = (function() {
        var cached_function = imageEditor.loadImageFromURL;
        function waitUntilImageEditorIsUnlocked(imageEditor) {
            return new Promise((resolve,reject)=>{
                const interval = setInterval(()=>{
                    if (!imageEditor._invoker._isLocked) {
                        clearInterval(interval);
                        resolve();
                    }
                }, 100);
            })
        }
        return function() {
            return waitUntilImageEditorIsUnlocked(imageEditor).then(()=>cached_function.apply(this, arguments));
        };
    })();
    

    第三个问题可以通过获取loadImageFromURL返回的promise所解析的对象并将新旧宽度/高度属性传递给ui.resizeEditor函数来解决,如下所示:

    imageEditor.loadImageFromURL("https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg/526px-Wikipedia-logo-v2.svg.png", "SampleImage").then(result=>{
        imageEditor.ui.resizeEditor({
            imageSize: {oldWidth: result.oldWidth, oldHeight: result.oldHeight, newWidth: result.newWidth, newHeight: result.newHeight},
        });
    }).catch(err=>{
        console.error("Something went wrong:", err);
    })
    

    第四个问题可能有点令人困惑。让我解释。在网站上,您可以使用 <img> 标签包含几乎任何您想要的外部图像,但如果您想使用 JavaScript 访问外部图像,提供图像的服务器必须明确允许您使用 access-control-allow-origin标题。 例如,在 Amazon S3 上,服务器默认不允许这样做。您必须手动设置服务器以允许您或任何域访问它。见here。 如果您使用不同的服务器,例如,您可以将access-control-allow-origin 设置为*,就像维基百科对this image 所做的那样。然后您(和图像编辑器)可以从任何域的 JavaScript 访问该图像。

    【讨论】:

    • 感谢您的精彩回答。它为我节省了很多时间。 @Forivin
    • 疯狂的是这不是内置到库中的。非常感谢您的回答。
    • 对于最新版本,imageEditor._isLocked 有效,但 imageEditor._invoker._isLocked 无效。
    【解决方案2】:

    对于那些使用 Rails 的人来说,当遇到@Forivin 提出的第四个问题时,我就是这样做的。

    问题是当 Toast 调用存储在 S3 上的图像时,我会在 Chrome 上收到 CORS 错误,但 firefox 很好。有很多关于这方面的文章,基本上我发现最好的方法是在我的代码中使用代理。我仍然可以让我的 CORS 源指向我的主机,并且由于呼叫是通过代理从我的主机发出的,所以 S3 和 Chrome 很高兴。我的 S3 CORS 配置如下所示(允许子域):

    <?xml version="1.0" encoding="UTF-8"?>
    <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://*.mycompany.com</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    </CORSConfiguration>
    

    在您的 Rails 项目中执行以下操作:

    在您的 Gemfile 中添加 rack-proxy gem

    gem 'rack-proxy'
    

    创建代理文件。 s3 路径经过 URI 编码并附加到路由的末尾。该路由仅用于代理,因此它可以是任何东西,因为它将被重新路由到 s3。

    app/proxy/s3_proxy.rb

    class S3Proxy < Rack::Proxy
    
      def perform_request(env)
        if env['REQUEST_PATH'] =~ %r{^/my/dummy/path}
          s3_path = CGI.unescape(env['REQUEST_PATH'][15..-1])
    
          uri = URI.parse(s3_path)
          env['HTTP_HOST'] = uri.host
          env['SERVER_PORT'] = uri.port
          env['REQUEST_PATH'] = s3_path
          env['REQUEST_URI'] = s3_path
          env['PATH_INFO'] = s3_path
          env['rack.url_scheme'] = 'https'
    
          super(env)
        else
          @app.call(env)
        end
      end
    
    end
    

    添加到application.rb 文件:

    require "./app/proxy/s3_proxy"
    
    class Application < Rails::Application
      ...
    
      config.middleware.use S3Proxy
    end
    

    routes.rb

    get "/my/dummy/path/:s3_url", to: "my_controller#dummy_path"
    

    my_controller.rb 中的控制器方法。在这里渲染什么都没关系,因为它将被代理重定向。我们可能没有办法逃脱,因为代理无论如何都会改变。

      def dummy_path
        render plain: ""
      end
    

    最后在我的 Vue 代码中,我调用 Toast 编辑器,首先填充一个空白图像。然后在安装组件时,我加载 s3 图像并覆盖现有图像并调整画布大小。我发现在读取 s3 图像之前安装它需要稍微延迟。 s3 图像是我在 props 中传递的预签名 url。

    <template lang="pug">
    .v-image-editor-tool
      tui-image-editor(:include-ui='useDefaultUI' :options="editorOptions" ref="tuiImageEditor")
    </template>
    
    <script lang="coffee">
    import { ImageEditor } from '@toast-ui/vue-image-editor'
    import 'tui-image-editor/dist/tui-image-editor.min.css'
    
    export default app =
      props: ['imageUrl']
      data: ->
        useDefaultUI: true
        editorOptions:
          cssMaxWidth: 700
          cssMaxHeight: 700
          usageStatistics: false
          includeUI:
            loadImage:
              path: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
              name: 'Blank'
            menuBarPosition: 'bottom'
    
      mounted: ->
        fn = => this.$refs.tuiImageEditor.invoke('loadImageFromURL', @imageUrl, 'Image').then (result) =>
          this.$refs.tuiImageEditor.invoke('ui.resizeEditor', { imageSize: { newWidth: result.newWidth, newHeight: result.newHeight }})
        setTimeout(fn, 600)
    
      components:
        'tui-image-editor': ImageEditor
    </script>
    
    

    【讨论】:

      【解决方案3】:

      在打开图片之前将此属性添加到要编辑的图片标签中:

      crossorigin="anonymous"
      

      如此处所述: https://github.com/nhn/tui.image-editor/issues/68#issuecomment-930106372

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-25
        • 1970-01-01
        相关资源
        最近更新 更多