diff --git a/package.json b/package.json index 4e2abfa..48b0248 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "eslint": "^4.8.0", "eslint-plugin-react": "^7.4.0", "gl-react": "^2.2.8", - "gl-react-image": "0.0.2", "gl-react-native": "^2.38.0" }, "devDependencies": { diff --git a/src/Image.js b/src/Image.js new file mode 100644 index 0000000..dc22594 --- /dev/null +++ b/src/Image.js @@ -0,0 +1,107 @@ +import GL from "gl-react"; +import React from "react"; +import rectCrop from "rect-crop"; +import rectClamp from "rect-clamp"; +import PropTypes from 'prop-types'; + +const shaders = GL.Shaders.create({ + image: { + frag: ` +precision highp float; +varying vec2 uv; +uniform sampler2D t; +uniform vec4 crop; +vec2 invert (vec2 p) {${""/* y is reversed in gl context */} + return vec2(p.x, 1.0-p.y); +} +void main () { + vec2 p = invert(invert(uv) * crop.zw + crop.xy); + gl_FragColor = + step(0.0, p.x) * + step(0.0, p.y) * + step(p.x, 1.0) * + step(p.y, 1.0) * + texture2D(t, p); +}` + } +}); + +const Image = GL.createComponent( +({ + width, + height, + source, + imageSize, + resizeMode = "cover", + center, + zoom, +}) => { + if (!imageSize) { + if (source.width && source.height) { + imageSize = { width: source.width, height: source.height }; + } + else { + throw new Error("gl-rect-image: imageSize is required if you don't provide {width,height} in source"); + } + } + let crop; + switch (resizeMode) { + case "cover": { + if (!center) center = [ 0.5, 0.5 ]; + if (!zoom) zoom = 1; + let rect = rectCrop(zoom, center)({ width, height }, imageSize); + rect = rectClamp(rect, [ 0, 0, imageSize.width, imageSize.height ]); + crop = [ + rect[0] / imageSize.width, + rect[1] / imageSize.height, + rect[2] / imageSize.width, + rect[3] / imageSize.height + ]; + break; + } + case "contain": { + if (center || zoom) { + console.warn("gl-react-image: center and zoom props are only supported with resizeMode='cover'"); + } + const ratio = width / height; + const imageRatio = imageSize.width / imageSize.height; + crop = + ratio > imageRatio + ? [ (1 - ratio / imageRatio) / 2, 0, ratio / imageRatio, 1 ] + : [ 0, (1 - imageRatio / ratio) / 2, 1, imageRatio / ratio ]; + break; + } + case "stretch": + if (center || zoom) { + console.warn("gl-react-image: center and zoom props are only supported with resizeMode='cover'"); + } + crop = [ 0, 0, 1, 1 ]; + break; + + default: + throw new Error("gl-react-image: unknown resizeMode="+resizeMode); + } + + return ; +}, + { + displayName: "Image", + propTypes: { + source: PropTypes.any.isRequired, + imageSize: PropTypes.shape({ + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + }), + resizeMode: PropTypes.string, + } + }); + +module.exports ={ + Image, +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4b9220f..b33604e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -961,13 +961,6 @@ github@^12.0.0: mime "^2.0.3" netrc "^0.1.4" -gl-react-image@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/gl-react-image/-/gl-react-image-0.0.2.tgz#61c573f6b59d036c58d3f64934f0cd426f437deb" - dependencies: - rect-clamp "0.0.0" - rect-crop "0.0.0" - gl-react-native@^2.38.0: version "2.47.0" resolved "https://registry.yarnpkg.com/gl-react-native/-/gl-react-native-2.47.0.tgz#0d2418314973f6bd3bd7f83acf776caa61339baf"