4

キャンバスを円筒形の円錐として提示したいと思います。これは、車輪のように両方向に回転できます。これは JS/CSS3 で可能ですか?

4

2 に答える 2

5

この新しい CSS3 機能を見てください:カスタム フィルター / CSS シェーダー.

以下は、私ができるよりも全体を説明している本当に素晴らしいプレゼンテーションです (Chrome で有効にする方法、開始方法、動作方法など)。

基本的に、シェーダーと CSS3 トランスフォームに既に精通している場合は、すべて完了しています...

利点

  • WebGl のような GPU/3D アクセラレーション
  • JS フリー ( GL シェーダーと CSSのみ)
  • CSS3 トランジションと組み合わせる可能性

不便

  • 新機能 /一部のブラウザの最近のバージョンでのみサポートされています (フラグで保護されている場合があります)
  • シェーダー用の独立したファイル (それについては不明です - WebGL のように HTML ページでそれらをインライン化することが何らかの方法で可能かもしれません)
  • 以下に説明する例を実装しているときに、奇妙な動作に遭遇しました: キャンバスのサイズ(CSS サイズではなく、ピクセル密度を定義する「JS」サイズ)が大きくなりすぎると、シェーダーが適用されないように見えます。キャンバス上で行っているかどうかに関係なく、もう。なぜか気になるので調べてみます。

より正確な要件 (円筒形の円錐としてのキャンバス) に答えるために、この小さな例を作成しました: http://aldream.net/various/css-shader-demo/cylindricalConeTransformDemo.html。キャンバスの上にカーソルを置いて、円錐にラップします。

回転しません。上記の記事の 1 つの例から取った単純なトランジション効果を適用しただけですが、アイデアは理解できるはずです。

使用されている頂点シェーダーとフラグメント シェーダーは次の場所にあります。

簡略化およびコメント化されたコード

  • CSS
    canvas {
        /* ... Prettify it as you wish */

        width: 640px;
        height: 560px;

        -webkit-filter: custom(url(cylindricalConeTransform.vs) /* Vertex-shader */
            mix(url(cylindricalConeTransform.fs) normal source-atop /* Fragment-shader and color-mixing properties */),
            36 2 /* Numbers of vertices */,
            /* Passing the values to the shaders uniforms: */
            amount 0,
            cylinderRadius 0.35,
            cylinderLength 250,
            transform rotateY(0deg) rotateX(0deg));

        -webkit-transition: -webkit-filter linear 1s; /* Transition on the filter for animation. */

    }

    canvas:hover {
        /* Same as above, but with different values for some uniforms. With the CSS-transition, those values will be tweened. */
        filter: custom(url(cylindricalConeTransform.vs) mix(url(cylindricalConeTransform.fs) normal source-atop), 36 2,
            amount 1,
            cylinderRadius 0.35,
            cylinderLength 250,
            transform rotateY(60deg) rotateX(60deg));
    }
  • 頂点シェーダー
precision mediump float;

// Built-in attributes
attribute vec4 a_position;
attribute vec2 a_texCoord;

// Built-in uniforms
uniform mat4 u_projectionMatrix;

// Uniforms passed in from CSS
uniform float amount;
uniform float cylinderRadius;
uniform float cylinderLength;
uniform mat4 transform;

// Constants
const float PI = 3.1415;

// Cone function
vec3 computeCylindricalConePosition( vec2 uv, float r, float l ) {
    vec3 p;
    float fi = uv.x * PI * 2.0;

    p.x = r * cos( fi ) * uv.y;
    p.y = r * sin( fi ) * uv.y;
    p.z = (uv.y - 0.5) * l;
    return p;
}

// Main
void main() {
    vec4 position = a_position;

    // Map plane to cone using UV coordinates
    vec3 cone = computeCylindricalConePosition( a_texCoord, cylinderRadius, cylinderLength );

    // Blend plane and cone
    position.xyz = mix( position.xyz, cone, amount );

    // Set vertex position
    gl_Position = u_projectionMatrix * transform * position;
}
  • フラグメントシェーダー
/** spec: css */
precision mediump float;

void main() {
    css_ColorMatrix = mat4(
        1.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0,
        0.0, 0.0, 1.0, 0.0,
        0.0, 0.0, 0.0, 1.0
    );
}
  • HTML
<!doctype html>
<html>
<head>
    ... your meta, css, ...
<body>

    <canvas></canvas>

    <script>
        // Draw what you want in your canvas.
    </script>
</body>
</html>

編集:円錐または円柱のどちらを求めているのか実際にはわかりませんが、ここでは違いはわずかです。2 番目が必要な場合は、頂点シェーダーのcomputeCylindricalConePosition()関数を変更し、代わりに次のように px と py を評価します。

p.x = r * cos( fi ) /* * uv.y */;
p.y = r * sin( fi ) /* * uv.y */;

お役に立てば幸いです。いくつかの点を明確にしたら、答えを発展させようとします。

于 2013-05-09T16:36:34.743 に答える