私は画像や動画をクリップする必要がある状況があります。画像や動画は重なり合う必要があります。これはもともとSVGで試してみましたが、いろいろな理由でうまくいきませんでしたので、キャンバスでやっています。キャンバスを通って動画をクリップする最も効率的な方法は何ですか
これは画像でうまくいきましたが、ビデオになると、ブラウザは約2分後にはほとんど停止してしまいます。 (サンプル・コードまたはリンクから表示されませんどのようなことが考慮されていないですが、我々はまた、ビデオを一時停止している、とタブが表示されていない間、ということである。)ここで
はリンクです: http://codepen.io/paceaux/pen/egLOeR チーフ懸念のはこの方法です:
drawFrame() {
if (this.isVideo && this.media.paused) return false;
let x = 0;
let width = this.media.offsetWidth;
let y = 0;
this.imageFrames[this.module.dataset.imageFrame](this.backContext);
this.backContext.drawImage(this.media, x, y, width, this.canvas.height);
this.context.drawImage(this.backCanvas, 0, 0);
if (this.isVideo) {
window.requestAnimationFrame(()=>{
this.drawFrame();
});
}
}
あなたはすぐに減速し、ブラウザを観察します。私はあまりにもひどく長い間、そのコードペインを見ることはお勧めしません。
私は"backCanvas" techniqueを使用していますが、状況が悪化するようです。
私はまた、クリップのパスを保存するためにPath2D()
を使用しようとしましたが、あまり役に立ちません。
その他の最適化はありますか? (ビデオのサイズを保存します)。
let imageFrames = function() {
\t let defaults = {
\t \t wedgeHeight: 50
\t };
\t return {
\t \t defaults: defaults,
\t \t //all wedges draw paths clockwise: top right, bottom right, bottom left, top left
\t \t wedgeTop: (context, wedgeHeight = defaults.wedgeHeight) => {
\t \t \t var wedge = new Path2D();
\t \t \t wedge.moveTo(this.dimensions.width, 0);
\t \t \t wedge.lineTo(this.dimensions.width, this.dimensions.height);
\t \t \t wedge.lineTo(0, this.dimensions.height);
\t \t \t wedge.lineTo(0, wedgeHeight);
\t \t \t wedge.closePath();
\t \t \t context.clip(wedge);
\t \t },
\t \t wedgeTopReverse: (context, wedgeHeight = defaults.wedgeHeight) => {
\t \t \t var wedge = new Path2D();
\t \t \t wedge.moveTo(this.dimensions.width, wedgeHeight);
\t \t \t wedge.lineTo(this.dimensions.width, this.dimensions.height);
\t \t \t wedge.lineTo(0, this.dimensions.height);
\t \t \t wedge.lineTo(0, 0);
\t \t \t wedge.closePath();
\t \t \t context.clip(wedge);
\t \t },
\t \t wedgeBottom: (context, wedgeHeight = defaults.wedgeHeight) => {
\t \t \t var wedge = new Path2D();
\t \t \t wedge.moveTo(this.dimensions.width, 0);
\t \t \t wedge.lineTo(this.dimensions.width, this.dimensions.height - wedgeHeight);
\t \t \t wedge.lineTo(0, this.dimensions.height);
\t \t \t wedge.lineTo(0,0);
\t \t \t wedge.closePath();
\t \t \t context.clip(wedge);
\t \t },
\t \t wedgeBottomReverse: (context, wedgeHeight = defaults.wedgeHeight) => {
\t \t \t var wedge = new Path2D();
\t \t \t wedge.moveTo(this.dimensions.width, 0);
\t \t \t wedge.lineTo(this.dimensions.width, this.dimensions.height);
\t \t \t wedge.lineto(0, this.dimensions.height - wedgeHeight);
\t \t \t wedge.lineTo(0, 0);
\t \t \t wedge.closePath();
\t \t \t context.clip(wedge);
\t \t }
\t };
};
class ImageCanvasModule {
\t constructor(module) {
\t \t this.module = module;
\t \t this.imageFrames = imageFrames.call(this);
\t \t if(this.isVideo) {
\t \t \t /*drawFrame has a check where it'll only draw on reqAnimationFrame if video.paused === false,
\t \t \t so we need to fire drawFrame on both events because that boolean will be false when it's paused, thus cancelling the animation frame
\t \t \t */
\t \t \t this.media.addEventListener('play',()=>{
\t \t \t \t this.drawOnCanvas();
\t \t \t });
\t \t \t this.media.addEventListener('pause',()=> {
\t \t \t \t this.drawOnCanvas();
\t \t \t });
\t \t }
\t }
\t get isPicture() {
\t \t return (this.module.nodeName === 'PICTURE');
\t }
\t get isVideo() {
\t \t return (this.module.nodeName === 'VIDEO');
\t }
\t get media() {
\t \t return this.isPicture ? this.module.querySelector('img') : this.module;
\t }
\t get context() {
\t \t return this.canvas.getContext('2d');
\t }
\t get dimensions() {
\t \t return {
\t \t \t width: this.module.offsetWidth,
\t \t \t height: this.module.offsetHeight
\t \t };
\t }
\t createCanvas() {
\t \t let canvas = document.createElement('canvas');
\t \t this.module.parentNode.insertBefore(canvas, this.module.nextSibling);
\t \t canvas.className = this.module.className;
\t \t this.canvas = canvas;
\t \t this.createBackContext();
\t }
\t createBackContext() {
\t \t this.backCanvas = document.createElement('canvas');
\t \t this.backContext = this.backCanvas.getContext('2d');
\t \t this.backCanvas.width = this.dimensions.width;
\t \t this.backCanvas.height = this.backCanvas.height;
\t }
\t sizeCanvas() {
\t \t this.canvas.height = this.dimensions.height;
\t \t this.canvas.width = this.dimensions.width;
\t \t this.backCanvas.height = this.dimensions.height;
\t \t this.backCanvas.width = this.dimensions.width;
\t }
\t drawFrame() {
\t \t if (this.isVideo && this.media.paused) return false;
\t \t let x = 0;
\t \t let width = this.media.offsetWidth;
\t \t let y = 0;
\t \t
\t \t this.imageFrames[this.module.dataset.imageFrame](this.backContext);
\t \t this.backContext.drawImage(this.media, x, y, width, this.canvas.height);
\t \t this.context.drawImage(this.backCanvas, 0, 0);
\t \t if (this.isVideo) {
\t \t \t window.requestAnimationFrame(()=>{
\t \t \t \t this.drawFrame();
\t \t \t });
\t \t }
\t }
\t drawOnCanvas() {
\t \t this.sizeCanvas();
\t \t this.drawFrame();
\t }
\t hideOriginal() {
\t \t //don't use display: none .... you can't get image dimensions when you do that.
\t \t this.module.style.opacity = 0;
\t }
}
console.clear();
window.addEventListener('DOMContentLoaded',()=> {
\t var els = document.querySelectorAll('.canvasify');
\t var canvasified = [];
\t for (el of els) {
\t \t if (el.dataset.imageFrame) {
\t \t \t let imageModule = new ImageCanvasModule(el);
\t \t \t imageModule.createCanvas();
\t \t \t imageModule.drawOnCanvas();
\t \t \t imageModule.hideOriginal();
\t \t \t canvasified.push(imageModule);
\t \t }
\t }
\t console.log(canvasified);
});
body {
\t background-color: #333;
}
.container {
\t height: 600px;
\t width: 100%;
\t position: relative;
\t display: flex;
\t flex-direction: column;
\t justify-content: center;
}
.container + .container {
\t margin-top: -150px;
}
.canvasify {
\t position:absolute;
\t top: 0;
\t left: 0;
\t right: 0;
\t bottom: 0;
\t width: 100%;
\t z-index: -1;
}
video {
\t width: 100%
}
h1 {
\t font-size: 2em;
\t color: #ddd;
}
<div class="container">
\t <img class="canvasify" data-image-frame="wedgeTop" src="http://placekitten.com/1280/500" />
\t <h1>Kitty with a clipped top</h1>
</div>
<div class="container">
<video controls muted class="canvasify" loop autoplay data-image-frame="wedgeTop">
<source src="https://poc5.ssl.cdn.sdlmedia.com/web/635663565028367012PU.mp4">
</video>
\t <h1>video with a clipped top that overlaps the image above</h1>
</div>
問題がcodepen(このコードを実行している他のページ)が非常に遅いということです。何が最適化されていないか、または間違って使用されていますか?どのように他の人のコードに私のコードを比較することから、
「オーバーラップ」とはどういう意味ですか?何が問題なの? – guest271314
ページが極端に遅くなるという問題があります。 「オーバーラップ」とは、ビデオの画像をクリップし、その画像の上に重なる画像を重ねることを意味します。ビデオ/画像は長方形ではなく、角度で切り取ったように見えます。 – paceaux
まだありません。私はあなたがcodepenで見るものを正確に探しています。 2つの別々の容器。 1つは画像を含むかもしれない。もう1つはビデオを含むかもしれない。各コンテナはビデオまたはイメージのいずれかを持ち、ある角度で「クリップ」されます。 HTMLのようなテキストがイメージ/ビデオの上に座ります。したがって、1つのコンテナ内の画像の下端が、ビデオであるかもしれないものの上端の下に視覚的に表示されます。 私はそれを行う方法については助けが必要ではありません(私はすでにそれを行いました。)ページのパフォーマンスを向上させる助けが必要です。 – paceaux