html 如何使用帆布使底壁变圆

xdnvmnnf  于 2023-02-20  发布在  其他
关注(0)|答案(1)|浏览(97)

我在ball2.js工作。我有一个有4面墙的盒子里的可拖动的球。球是可拖动的,可拉动的。我想更新我的底部直墙到一个小曲线,所以它会看起来像一个碗。任何帮助将不胜感激
球JS(文件)

var canvas;
let xyz = 1;
var delta = [ 0, 0 ];
var stage = [ window.screenX, window.screenY, window.innerWidth, window.innerHeight ];
getBrowserDimensions();

var themes = [ [ "#10222B", "#95AB63", "#BDD684", "#E2F0D6", "#F6FFE0" ],
         ]; // Here you can add/remove the theme colours.
var theme;

var worldAABB, world, iterations = 1, timeStep = 1 / 15;

var walls = [];
var wall_thickness = 200;
var wallsSetted = false;

var bodies, elements, text;

var createMode = false;
var destroyMode = false;

var isMouseDown = false;
var mouseJoint;
var mouse = { x: 0, y: 0 };
var gravity = { x: 0, y: 1 };

var PI2 = Math.PI * 2;

var timeOfLastTouch = 0;

init();
play();

function init() {

    canvas = document.getElementById("canvas");
    console.log(canvas);
    canvas.style.borderTopLeftRadius = "20px";
    // canvas.style[ 'backgroundColor' ] = "#000";
    // var ctx = canvas.getContext("2d");
    // ctx.fillStyle = "blue";
    document.onmousedown = onDocumentMouseDown;
    document.onmouseup = onDocumentMouseUp;
    document.onmousemove = onDocumentMouseMove;
    document.ondblclick = onDocumentDoubleClick;

    document.addEventListener( 'touchstart', onDocumentTouchStart, false );
    document.addEventListener( 'touchmove', onDocumentTouchMove, false );
    document.addEventListener( 'touchend', onDocumentTouchEnd, false );

    window.addEventListener( 'deviceorientation', onWindowDeviceOrientation, false );

    // init box2d

    worldAABB = new b2AABB();
    worldAABB.minVertex.Set( -200, -200 );
    worldAABB.maxVertex.Set( window.innerWidth + 200, window.innerHeight + 200 );

    world = new b2World( worldAABB, new b2Vec2( 0, 0 ), true );

    setWalls();
    reset();
}

function play() {

    setInterval( loop, 1000 / 40 );
}

function reset() {

    var i;

    if ( bodies ) {

        for ( i = 0; i < bodies.length; i++ ) {

            var body = bodies[ i ]
            canvas.removeChild( body.GetUserData().element );
            world.DestroyBody( body );
            body = null;
        }
    }

    // color theme
    theme = themes[ Math.random() * themes.length >> 0 ];
    // document.body.style[ 'backgroundColor' ] = "#e2e2e2";
    

    bodies = [];
    elements = [];

    // createInstructions();

    for( i = 0; i < 50; i++ ) {

        createBall();

    }

}

//

function onDocumentMouseDown() {

    isMouseDown = true;
    return false;
}

function onDocumentMouseUp() {

    isMouseDown = false;
    return false;
}

function onDocumentMouseMove( event ) {

    mouse.x = event.clientX + 0;
    mouse.y = event.clientY + 250;
}

function onDocumentDoubleClick() {

    reset();
}

function onDocumentTouchStart( event ) {

    if( event.touches.length == 1 ) {

        event.preventDefault();

        // Faking double click for touch devices

        var now = new Date().getTime();

        if ( now - timeOfLastTouch  < 250 ) {

            reset();
            return;
        }

        timeOfLastTouch = now;

        mouse.x = event.touches[ 0 ].pageX;
        mouse.y = event.touches[ 0 ].pageY;
        isMouseDown = true;
    }
}

function onDocumentTouchMove( event ) {

    if ( event.touches.length == 1 ) {

        event.preventDefault();

        mouse.x = event.touches[ 0 ].pageX;
        mouse.y = event.touches[ 0 ].pageY;

    }

}

function onDocumentTouchEnd( event ) {

    if ( event.touches.length == 0 ) {

        event.preventDefault();
        isMouseDown = false;

    }

}

function onWindowDeviceOrientation( event ) {

    if ( event.beta ) {

        gravity.x = Math.sin( event.gamma * Math.PI / 180 );
        gravity.y = Math.sin( ( Math.PI / 4 ) + event.beta * Math.PI / 180 );

    }

}

//

function createInstructions() {

    var size = 250;

    var element = document.createElement( 'div' );
    element.width = size;
    element.height = size;  
    element.style.position = 'absolute';
    element.style.left = -200 + 'px';
    element.style.top = -200 + 'px';
    element.style.cursor = "default";

    canvas.appendChild(element);
    elements.push( element );

    var circle = document.createElement( 'canvas' );
    circle.width = size;
    circle.height = size;

    var graphics = circle.getContext( '2d' );

    graphics.fillStyle = theme[ 3 ];
    graphics.beginPath();
    graphics.arc( size * .5, size * .5, size * .5, 0, PI2, true );
    graphics.closePath();
    graphics.fill();

    element.appendChild( circle );

    text = document.createElement( 'div' );
    text.onSelectStart = null;
    text.innerHTML = '<span style="color:' + theme[0] + ';font-size:40px;">Hello!</span><br /><br /><span style="font-size:15px;"><strong>This is how it works:</strong><br /><br />1. Drag a ball.<br />2. Double click to change colors.<br />3. Shake your browser.<br />4. Click Background.<br />5. Play!</span>';
    text.style.color = theme[1];
    text.style.position = 'absolute';
    text.style.left = '0px';
    text.style.top = '0px';
    text.style.fontFamily = 'Georgia';
    text.style.textAlign = 'center';
    element.appendChild(text);

    text.style.left = ((250 - text.clientWidth) / 2) +'px';
    text.style.top = ((250 - text.clientHeight) / 2) +'px'; 

    var b2body = new b2BodyDef();

    var circle = new b2CircleDef();
    circle.radius = size / 2;
    circle.density = 1;
    circle.friction = 0.3;
    circle.restitution = 0.3;
    b2body.AddShape(circle);
    b2body.userData = {element: element};

    b2body.position.Set( Math.random() * stage[2], Math.random() * -200 );
    b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
    bodies.push( world.CreateBody(b2body) );    
}

function createBall( x, y ) {

    // console.log(xyz);
    xyz++;

    if(xyz == 1){
        var img = document.getElementById("coin1")
    }else if(xyz == 2){
        var img = document.getElementById("coin2")
    }else if(xyz == 3){
        var img = document.getElementById("coin3")
    }else if(xyz == 4){
        var img = document.getElementById("coin4")
    }else if(xyz == 5){
        var img = document.getElementById("coin5")
    }else if(xyz == 6){
        var img = document.getElementById("coin6")
    }else if(xyz == 7){
        var img = document.getElementById("coin7")
    }else if(xyz == 8){
        var img = document.getElementById("coin8")
    }else if(xyz == 9){
        var img = document.getElementById("coin9")
    }else if(xyz == 10){
        var img = document.getElementById("coin10")
    }else if(xyz == 11){
        var img = document.getElementById("coin11")
    }else if(xyz == 12){
        var img = document.getElementById("coin12")
    }else if(xyz == 13){
        var img = document.getElementById("coin13")
    }else if(xyz == 14){
        var img = document.getElementById("coin14")
    }else if(xyz == 15){
        var img = document.getElementById("coin15")
    }else if(xyz == 16){
        var img = document.getElementById("coin16")
    }else if(xyz == 17){
        var img = document.getElementById("coin17")
    }else if(xyz == 18){
        var img = document.getElementById("coin18")
    }else if(xyz == 19){
        var img = document.getElementById("coin19")
    }else if(xyz == 20){
        var img = document.getElementById("coin20")
    }else if(xyz == 21){
        var img = document.getElementById("coin21")
    }else if(xyz == 22){
        var img = document.getElementById("coin22")
    }else if(xyz == 23){
        var img = document.getElementById("coin23")
    }else if(xyz == 24){
        var img = document.getElementById("coin24")
    }else if(xyz == 25){
        var img = document.getElementById("coin25")
    }else if(xyz == 26){
        var img = document.getElementById("coin26")
    }else if(xyz == 27){
        var img = document.getElementById("coin27")
    }else if(xyz == 28){
        var img = document.getElementById("coin28")
    }else if(xyz == 29){
        var img = document.getElementById("coin29")
    }else if(xyz == 30){
        var img = document.getElementById("coin30")
    }else if(xyz == 31){
        var img = document.getElementById("coin31")
    }else if(xyz == 32){
        var img = document.getElementById("coin32")
    }else if(xyz == 33){
        var img = document.getElementById("coin33")
    }else if(xyz == 34){
        var img = document.getElementById("coin34")
    }else if(xyz == 35){
        var img = document.getElementById("coin35")
    }else if(xyz == 36){
        var img = document.getElementById("coin36")
    }else if(xyz == 37){
        var img = document.getElementById("coin37")
    }else if(xyz == 38){
        var img = document.getElementById("coin38")
    }else if(xyz == 39){
        var img = document.getElementById("coin39")
    }else if(xyz == 40){
        var img = document.getElementById("coin40")
    }else if(xyz == 41){
        var img = document.getElementById("coin41")
    }else if(xyz == 42){
        var img = document.getElementById("coin42")
    }else if(xyz == 43){
        var img = document.getElementById("coin43")
    }else if(xyz == 44){
        var img = document.getElementById("coin44")
    }else if(xyz == 45){
        var img = document.getElementById("coin45")
    }else if(xyz == 46){
        var img = document.getElementById("coin46")
    }else if(xyz == 47){
        var img = document.getElementById("coin47")
    }else if(xyz == 48){
        var img = document.getElementById("coin48")
    }else if(xyz == 49){
        var img = document.getElementById("coin49")
    }
    else{
        var img = document.getElementById("coin50")
    }

    var x = x || Math.random() * stage[2];
    var y = y || Math.random() * -200;

    var size = (Math.random() * 100 >> 0) + 20;

    var element = document.createElement("canvas");
    element.width = size;
    element.height = size;
    element.style.position = 'absolute';
    element.style.left = -200 + 'px';
    element.style.top = -200 + 'px';
    element.style.WebkitTransform = 'translateZ(0)';
    element.style.MozTransform = 'translateZ(0)';
    element.style.OTransform = 'translateZ(0)';
    element.style.msTransform = 'translateZ(0)';
    element.style.transform = 'translateZ(0)';

    var graphics = element.getContext("2d");
    var num_circles = Math.random();

    for (var i = size; i > 0; i-= (size/num_circles)) {

    
        
        
        graphics.drawImage(img,0,0, size , size);
        graphics.arc(size * .5, size * .5, i * .5, 0, PI2, true); 
        canvas.appendChild(element);
        elements.push( element );
        // graphics.arc(size, size, i, 0, PI2, true); 
        // graphics.closePath();
        // graphics.fill();
    }

    

    var b2body = new b2BodyDef();

    var circle = new b2CircleDef();
    circle.radius = size >> 1;
    circle.density = 1;
    circle.friction = 0.3;
    circle.restitution = 0.3;
    b2body.AddShape(circle);
    b2body.userData = {element: element};

    b2body.position.Set( x, y );
    b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
    bodies.push( world.CreateBody(b2body) );
}

//

function loop() {

    if (getBrowserDimensions()) {

        setWalls();

    }

    delta[0] += (0 - delta[0]) * .5;
    delta[1] += (0 - delta[1]) * .5;

    world.m_gravity.x = gravity.x * 350 + delta[0];
    world.m_gravity.y = gravity.y * 350 + delta[1];

    mouseDrag();
    world.Step(timeStep, iterations);

    for (i = 0; i < bodies.length; i++) {

        var body = bodies[i];
        var element = elements[i];

        element.style.left = (body.m_position0.x - (element.width >> 1)) + 'px';
        element.style.top = (body.m_position0.y - (element.height >> 1)) + 'px';

        if (element.tagName == 'DIV') {

            var style = 'rotate(' + (body.m_rotation0 * 57.2957795) + 'deg) translateZ(0)';
            text.style.WebkitTransform = style;
            text.style.MozTransform = style;
            text.style.OTransform = style;
            text.style.msTransform = style;
            text.style.transform = style;

        }

    }

}

// .. BOX2D UTILS

function createBox(world, x, y, width, height, fixed) {

    if (typeof(fixed) == 'undefined') {

        fixed = true;

    }

    var boxSd = new b2BoxDef();

    if (!fixed) {

        boxSd.density = 1.0;

    }

    boxSd.extents.Set(width, height);

    var boxBd = new b2BodyDef();
    boxBd.AddShape(boxSd);
    boxBd.position.Set(x,y);

    return world.CreateBody(boxBd);

}

function createBox2(world, x, y, width, height, fixed) {

    if (typeof(fixed) == 'undefined') {

        fixed = true;

    }

var boxSd = new b2CircleDef();

    if (!fixed) {

        boxSd.density = 1.0;

    }
boxSd.radius = 100;

    var boxBd = new b2BodyDef();
    boxBd.AddShape(boxSd);
    boxBd.position.Set(x,y);

    return world.CreateBody(boxBd);

}

function mouseDrag()
{
    // mouse press
    if (createMode) {

        createBall( mouse.x, mouse.y );

    } else if (isMouseDown && !mouseJoint) {

        var body = getBodyAtMouse();

        if (body) {

            var md = new b2MouseJointDef();
            md.body1 = world.m_groundBody;
            md.body2 = body;
            md.target.Set(mouse.x, mouse.y);
            md.maxForce = 30000 * body.m_mass;
            // md.timeStep = timeStep;
            mouseJoint = world.CreateJoint(md);
            body.WakeUp();

        } else {

            // createMode = true;

        }

    }

    // mouse release
    if (!isMouseDown) {

        createMode = false;
        destroyMode = false;

        if (mouseJoint) {

            world.DestroyJoint(mouseJoint);
            mouseJoint = null;

        }

    }

    // mouse move
    if (mouseJoint) {

        var p2 = new b2Vec2(mouse.x, mouse.y);
        mouseJoint.SetTarget(p2);
    }
}

function getBodyAtMouse() {

    // Make a small box.
    var mousePVec = new b2Vec2();
    mousePVec.Set(mouse.x, mouse.y);

    var aabb = new b2AABB();
    aabb.minVertex.Set(mouse.x - 1, mouse.y - 1);
    aabb.maxVertex.Set(mouse.x + 1, mouse.y + 1);

    // Query the world for overlapping shapes.
    var k_maxCount = 10;
    var shapes = new Array();
    var count = world.Query(aabb, shapes, k_maxCount);
    var body = null;

    for (var i = 0; i < count; ++i) {

        if (shapes[i].m_body.IsStatic() == false) {

            if ( shapes[i].TestPoint(mousePVec) ) {

                body = shapes[i].m_body;
                break;

            }

        }

    }

    return body;

}

function setWalls() {

    if (wallsSetted) {

        world.DestroyBody(walls[0]);
        world.DestroyBody(walls[1]);
        world.DestroyBody(walls[2]);
        world.DestroyBody(walls[3]);

        walls[0] = null; 
        walls[1] = null;
        walls[2] = null;
        walls[3] = null;
    }

    walls[0] = createBox(world, stage[2] / 2, - wall_thickness, stage[2], wall_thickness);

    // Bottom Wall Starts
    walls[1] = createBox(world, stage[2], stage[3] + wall_thickness, stage[2], wall_thickness);
    // Bottom Wall Ends
    
//  function createBox(world, x, y, width, height, fixed) {

    // Left Wall
    walls[2] = createBox(world, - wall_thickness, stage[3] / 2, wall_thickness, stage[3]);
    // Left Wall

    // Right wall
    walls[3] = createBox(world, stage[2] + wall_thickness, stage[3] / 2, wall_thickness, stage[3]); 
    // Right Wall

    wallsSetted = true;

}

// BROWSER DIMENSIONS

function getBrowserDimensions() {

    var changed = false;

    if (stage[0] != window.screenX) {

        delta[0] = (window.screenX - stage[0]) * 50;
        stage[0] = window.screenX;
        changed = true;

    }

    if (stage[1] != window.screenY) {

        delta[1] = (window.screenY - stage[1]) * 50;
        stage[1] = window.screenY;
        changed = true;

    }

    if (stage[2] != window.innerWidth) {

        stage[2] = window.innerWidth;
        changed = true;

    }

    if (stage[3] != window.innerHeight) {

        stage[3] = window.innerHeight;
        changed = true;

    }

    return changed;

}

超文本标记语言

<div class="md:block hidden">
        <img src="{{ asset('/assets/img/coin-1.png') }}" id="coin1" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-2.png') }}" id="coin2" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-3.png') }}" id="coin3" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-4.png') }}" id="coin4" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-5.png') }}" id="coin5" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-6.png') }}" id="coin6" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-7.png') }}" id="coin7" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-8.png') }}" id="coin8" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-9.png') }}" id="coin9" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-10.png') }}" id="coin10" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-11.png') }}" id="coin11" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-12.png') }}" id="coin12" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-13.png') }}" id="coin13" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-14.png') }}" id="coin14" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-15.png') }}" id="coin15" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-16.png') }}" id="coin16" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-17.png') }}" id="coin17" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-18.png') }}" id="coin18" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-19.png') }}" id="coin19" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-20.png') }}" id="coin20" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-21.png') }}" id="coin21" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-22.png') }}" id="coin22" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-23.png') }}" id="coin23" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-24.png') }}" id="coin24" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-25.png') }}" id="coin25" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-26.png') }}" id="coin26" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-27.png') }}" id="coin27" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-28.png') }}" id="coin28" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-29.png') }}" id="coin29" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-30.png') }}" id="coin30" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-31.png') }}" id="coin31" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-32.png') }}" id="coin32" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-33.png') }}" id="coin33" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-34.png') }}" id="coin34" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-35.png') }}" id="coin35" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-36.png') }}" id="coin36" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-37.png') }}" id="coin37" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-38.png') }}" id="coin38" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-39.png') }}" id="coin39" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-40.png') }}" id="coin40" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-41.png') }}" id="coin41" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-42.png') }}" id="coin42" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-43.png') }}" id="coin43" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-44.png') }}" id="coin44" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-45.png') }}" id="coin45" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-46.png') }}" id="coin46" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-47.png') }}" id="coin47" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-48.png') }}" id="coin48" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-49.png') }}" id="coin49" style="display: none;" width="32" height="32">
        <img src="{{ asset('/assets/img/coin-50.png') }}" id="coin50" style="display: none;" width="32" height="32">

        <div>
            <div id="canvas"></div>
        </div>
    </div>

我把球放在盒子里,盒子有4面墙,这样球就不会跑到外面去。它是可以拖动的,可以放下的,可以在彼此之间推动的。我希望底部的墙有点弯曲,这样它看起来就像一个碗里的球。

qvtsj1bj

qvtsj1bj1#

Box 2D不支持凹形,只支持凸形,所以你需要用以下两种方法来近似你的曲线:
1.外部三角形Map到圆环的四分之一切片,圆环的内部是内壁
1.角点是所有三角形上的共享点,其他两个点(内部)从曲线计算。

  • 和-然后使他们连锁的形状,以避免粘在边缘(幽灵碰撞)。
    https://box2d.org/posts/2020/06/ghost-collisions/
    然而,由于球实际上被束缚在曲线之外,因为盒子防止球的周长接触到角落,你可以直接用图形绘制曲线,而不需要包含在box 2d中,因为box 2d检查是多余的。虽然这会防止球滚动,如果它们在重力下掉落并落在一边,即特别是为了拖或拉,这是可以的。

相关问题