pqina / filepond-plugin-image-preview

🖼 Show a preview for images dropped on FilePond
https://pqina.nl/filepond
MIT License
47 stars 27 forks source link

Status overlay (SVG mask) does not show #10

Closed robertvansteen closed 5 years ago

robertvansteen commented 5 years ago

When I upload an image via filepond the status overlay becomes a solid color, on further inspection it seems that the SVG mask is not displayed, causing the status color to fill the complete shape with a solid color.

screenshot 2018-12-18 at 08 44 41

Here is the code I use to set up Filepond.

import React from 'react';
import 'doka/doka.min.css';
import * as Doka from 'doka';
import cookie from 'js-cookie';
import Box from 'components/box';
import styled from 'library/styled';
import * as config from 'library/config';
import { File, FilePond, registerPlugin } from 'react-filepond';

import 'filepond/dist/filepond.min.css';
import FilePondPluginImageEdit from 'filepond-plugin-image-edit';
import FilePondPluginImageCrop from 'filepond-plugin-image-crop';
import FilePondPluginImageResize from 'filepond-plugin-image-resize';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import 'filepond-plugin-image-edit/dist/filepond-plugin-image-edit.css';
import FilePondPluginImageTransform from 'filepond-plugin-image-transform';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';

registerPlugin(
  FilePondPluginImageExifOrientation,
  FilePondPluginImagePreview,
  FilePondPluginImageCrop,
  FilePondPluginImageResize,
  FilePondPluginImageTransform,
  FilePondPluginImageEdit,
);

interface Props {
  required?: boolean;
  cropAspectRatio?: string | number | null;
  onChange: (value: any) => void;
  value?: any;
}

interface State {
  image: any;
}

export default class ImageUpload extends React.Component<Props> {
  /**
   * Define the default props.
   */
  static defaultProps = {
    cropAspectRatio: null,
  };

  /**
   * Get the derived state from the props.
   *
   * @static
   * @param {Props} props
   * @param {State} state
   */
  static getDerivedStateFromProps(props: Props, state: State) {
    return {
      image: state.image || props.value,
    };
  }

  /**
   * Define the initial state.
   */
  state = {
    image: null,
  };

  /**
   * Ref to the pond instance.
   */
  pond = React.createRef();

  /**
   * Server config.
   */
  getConfig() {
    const token = cookie.get('XSRF-TOKEN');

    if (!token) {
      throw new Error('Could not set up a secure connection with the server.');
    }

    return {
      url: config.api.uploadImage,
      process: {
        withCredentials: true,
        headers: {
          Accept: 'application/json',
          'X-XSRF-TOKEN': token,
        },
      },
    };
  }

  /**
   * Handle when the image is uploaded.
   */
  handleUpload = (error: any, file: any) => {
    if (error) throw error;
    this.props.onChange(file.serverId);
  };

  /**
   * Handle when the image is added.
   */
  handleUpdate = (files: Array<any>) => {
    this.setState({ image: files.length ? files[0].file : null });
  };

  /**
   * Handle when the image is removed.
   */
  handleRemoval = (file: any) => {
    this.props.onChange(null);
  };

  /**
   * Render the component.
   */
  render() {
    const { image } = this.state;
    const { cropAspectRatio, required } = this.props;

    return (
      <Box maxWidth="170px">
        <FilePond
          name="payload"
          ref={(ref: any) => (this.pond = ref)}
          required={required}
          allowRevert={false}
          allowMultiple={false}
          imageCropAspectRatio={cropAspectRatio}
          imageEditInstantEdit={false}
          imageEditEditor={Doka.create()}
          server={this.getConfig()}
          onprocessfile={this.handleUpload}
          onupdatefiles={this.handleUpdate}
          onremovefile={this.handleRemoval}
          labelIdle={`Drag & Drop your picture or <span class="filepond--label-action">Browse</span>`}
          imagePreviewHeight={170}
          imageResizeTargetWidth={100}
          imageResizeTargetHeight={100}
          stylePanelLayout="compact circle"
          styleButtonRemoveItemPosition="center bottom"
          styleProgressIndicatorPosition="center bottom"
          styleImageEditButtonEditItemPosition="right bottom"
        >
          {image && <File key={image} src={image} origin="local" />}
        </FilePond>
      </Box>
    );
  }
}

Versions:

    "filepond": "^3.5.1",
    "filepond-plugin-image-crop": "^2.0.0",
    "filepond-plugin-image-edit": "^1.0.1",
    "filepond-plugin-image-exif-orientation": "^1.0.3",
    "filepond-plugin-image-preview": "^3.1.4",
    "filepond-plugin-image-resize": "^2.0.1",
    "filepond-plugin-image-transform": "^3.1.0",
robertvansteen commented 5 years ago

Weirdly enough, sometimes it does work (like once every 10 attempts). Could it be some kind of race condition?

rikschennink commented 5 years ago

Hi Robert, that's weird indeed. The Image Preview plugin generates a sprite map at the root of the page (as a child of the body element). Maybe it's somehow removed? Does the React app live in a <div> as a child of <body>?

robertvansteen commented 5 years ago

@rikschennink Yes I'm using the default create-react-app template which renders React in a <div id="root" /> that is a direct descendant of <body>.

See: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/public/index.html

In the cases it does work (seemingly random) I indeed see a <svg> node as child of <body> and in the cases it does not work it's missing.

rikschennink commented 5 years ago

Okay, thanks for clarifying, my test environment is based on create-react-app as well so that should make it easier to test. Will get back to you later this week (again, probably Thursday).

rikschennink commented 5 years ago

I've just published a new version 3.1.5 of the image preview plugin that tries to add the SVG a bit earlier and is a bit more persistent in trying to add it. Can you give it a try and let me know if it fixes the issue.

robertvansteen commented 5 years ago

@rikschennink tested for a bit and the SVG mask displayed correctly every time I tried so seem to be resolved, thanks!

rikschennink commented 5 years ago

Fantastic! Thanks for confirming!

Zwimber commented 5 years ago

I have the exact same problem with a similar setup in Angular 7. Works on desktop and most other devices but iOS (latest version) with Safari is a source of trouble which gives the same green large box.

Updated all your packages to the latest version but problem remains. The solution mentioned here does solve the problem but is not quite as appealing.

@supports (-webkit-marquee-repetition: infinite) and (object-fit: fill) {
    .filepond--image-preview-overlay svg rect { display: none; }
    .filepond--image-preview-overlay svg { background: linear-gradient(currentColor 0%, transparent 66%); }
}

Any idea's?

rikschennink commented 5 years ago

@Zwimber Do you see the <svg> element that is generated by the image preview plugin, it should be appended to the element, somewhere near the end of the DOM.

screenshot 2019-02-04 at 09 54 31

Zwimber commented 5 years ago

Sorry for my late response, yes I do see the SVG element:

screenshot 2019-02-11 at 01 48 28

rikschennink commented 5 years ago

@Zwimber reproduced the issue, it's related to the <base> tag.

See this issue: https://github.com/airbnb/lottie-web/issues/360

Fixing it now.

rikschennink commented 5 years ago

Should be fixed in Image Preview plugin version 4.0.2

robertvansteen commented 5 years ago

I think this update actually broke it for me again, I'm getting the solid color like @Zwimber but it was working fine in 4.0.1

rikschennink commented 5 years ago

Haha oh no 🤦🏼‍♂️

Any <base> tag present in your code?

robertvansteen commented 5 years ago

This is the injected SVG code:

<svg class="filepond--image-preview-sprite" style="position: absolute; width: 0px; height: 0px;"><radialGradient id="filepond--image-preview-radial-gradient" cx=".5" cy="1.25" r="1.15">
<stop offset="50%" stop-color="#000000"></stop>
<stop offset="56%" stop-color="#0a0a0a"></stop>
<stop offset="63%" stop-color="#262626"></stop>
<stop offset="69%" stop-color="#4f4f4f"></stop>
<stop offset="75%" stop-color="#808080"></stop>
<stop offset="81%" stop-color="#b1b1b1"></stop>
<stop offset="88%" stop-color="#dadada"></stop>
<stop offset="94%" stop-color="#f6f6f6"></stop>
<stop offset="100%" stop-color="#ffffff"></stop>
</radialGradient>

<mask id="filepond--image-preview-masking">
<rect x="0" y="0" width="500" height="200" fill="url(http://localhost:3000#filepond--image-preview-radial-gradient)"></rect>
</mask></svg>
robertvansteen commented 5 years ago

There's no <base> tag in my code.

rikschennink commented 5 years ago

If it is there it’s probably in the <head> of the page.

rikschennink commented 5 years ago

Tried to reproduce with create-react-app but it seems to work correctly

robertvansteen commented 5 years ago

@rikschennink how exactly should it look? The <svg> should be wrapped in a <base> tag?

rikschennink commented 5 years ago

@rovansteen It's unrelated to the <svg>, it's literally an element called <base> that sits in the <head> of the website.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

robertvansteen commented 5 years ago

Ah, I didn't even know that existed. So I'm not using that. I'm guessing it has something to do with using push state routing, but it's weird that it was working fine before.

rikschennink commented 5 years ago

I've updated the plugin to change the contents of the url() value inside the SVG, maybe it conflicts with push state, will check later today.

rikschennink commented 5 years ago

Just published version 4.0.3, it should fix the issue @rovansteen

robertvansteen commented 5 years ago

@rikschennink thanks! Works perfectly again.

dnknitro commented 5 years ago

2019-04-19_01 10 44 It still occurs in React in Chrome @ "filepond": "^4.3.9", "filepond-plugin-file-metadata": "^1.0.6", "filepond-plugin-image-preview": "^4.0.8",

rikschennink commented 5 years ago

@dnknitro Please provide a publicly accessible test case