Abhishek Dhanraj Shahdeo
Abhishek Dhanraj Shahdeo

Reputation: 1356

3-D curvature fitting in html, css

I have seen people using transform to get 3-D effects.

But I didn't find anything very helpful if we need to rotate only some part of a <div>.

I would like to know how we can apply transformation to get concavial, convexial type etc 3-D effects.

What if we want to transform only 10% of this <div> or we want a transformation that increases and decreases from left to right or top to bottom ?

Or, consider a sphere and lets say you want to wrap a <div> over it, how could this be achieved ?

Upvotes: 0

Views: 199

Answers (2)

Kaiido
Kaiido

Reputation: 136866

At the moment of this writing, HTML elements are flat.
Even if CSS3 introduced 3D Tranforms, those are only for transforms, not for rendering shapes.

You can actually render a 3d cube made of 6 flat HTMLElements with such transformations, but still, they're flat.

see this David Walsh article on how to make a CSS Cube

We could probably adapt this idea to create a sphere, but for a sphere as smooth as the image below, it will involve 200 polygons, which means 200 different elements, each one with it's unique transform declaration, and you will have to break your content into every one of these elements.

a not so smooth sphere
I'll let you find the math to do something like this...

To render 3d objects in a web page, you can use the WebGL API, introduced with the html5 <canvas> element.

So, one solution, if you really need your content to get this 3d effect, would be to first get a snapshot of your element using a library like html2canvas, then use it as a texture in a webgl context.
Here is an example using three.js library.

var div = document.querySelector('div');
	html2canvas(div, {
	  onrendered: function(canvas) {
	    initCanvas(div, canvas.toDataURL());
	  }
	});

	function initCanvas(replacedElement, src) {
	  var size = replacedElement.getBoundingClientRect();

	  var scene = new THREE.Scene();
	  var camera = new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
	  var renderer = new THREE.WebGLRenderer();

	  renderer.setSize(size.width, size.height);
	  renderer.domElement.setAttribute('style', 'top:' + size.top + 'px; left:' + size.left + 'px; position:absolute;');
	  replacedElement.parentNode.insertBefore(renderer.domElement, replacedElement.nextNode);

	  var geometry = new THREE.SphereGeometry(0.5, 32, 32)
	  var material = new THREE.MeshPhongMaterial()


	  var sphere = new THREE.Mesh(geometry, material);
	  scene.add(sphere);
	  material.map = THREE.ImageUtils.loadTexture(src)
	  material.map.minFilter = THREE.LinearFilter;
	  var light = new THREE.PointLight('#FFF', 10, 100);
	  light.position.set(32, 32, 80);
	  scene.add(light);
	  camera.position.z = 1;

	  function render() {
	    requestAnimationFrame(render);
	    renderer.render(scene, camera);
	    sphere.rotation.x += .01
	    sphere.rotation.y += .01
	  }
	  render();
	}

window.onresize=function(){	html2canvas(div, {
	  onrendered: function(canvas) {
        var c = document.querySelector('canvas');
        if(c)c.parentNode.removeChild(c);
	    initCanvas(div, canvas.toDataURL());
	  }
	});}
div {
  background-color: rgba(255, 255, 255, 0.5);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<div>


  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet bibendum augue, nec convallis enim bibendum non. Donec sagittis finibus lorem nec porttitor. Donec vel tincidunt ante. Praesent semper luctus arcu, at eleifend nibh dapibus sit
    amet. Aenean maximus ex in luctus bibendum. Nullam in ligula quis tellus convallis rutrum. Vivamus id placerat metus. Morbi efficitur sem at cursus bibendum. Ut fermentum odio in lectus posuere accumsan. Etiam imperdiet metus at ornare tempus. Suspendisse
    nulla metus, aliquam viverra elementum sed, consequat ac est. Sed lorem neque, finibus ac ultricies vel, ullamcorper ut nibh. Praesent est nulla, dictum eu commodo nec, sollicitudin condimentum ante.
  </p>
  <p>
    Donec metus nulla, rutrum ultrices elementum quis, blandit ac nisl. Etiam fermentum pharetra dui, vel eleifend ante blandit nec. Nunc varius eget arcu sit amet fermentum. Sed lorem turpis, mattis suscipit orci ut, feugiat volutpat dolor. Ut eu est dolor.
    Nulla aliquam libero at libero maximus, eget porta lorem malesuada. Curabitur in odio dolor. Praesent iaculis feugiat ipsum at malesuada. Nulla sed commodo leo, at fringilla arcu. Nulla tempus tellus sit amet augue sodales efficitur. Vestibulum tristique
    nunc et eros ornare, et mollis mi pellentesque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
  </p>
  <p>
    Donec eu posuere sem. Etiam et massa non purus vehicula feugiat. Integer porta velit metus, eget tempor purus posuere non. Nam aliquam, lectus nec finibus venenatis, nunc urna porta lorem, commodo vehicula ex ante at augue. Vivamus nec erat sit amet nibh
    congue ullamcorper eget a eros. Integer varius turpis ut ex mollis, nec scelerisque est pretium. Phasellus nec lorem convallis, tincidunt ligula nec, ornare metus. Vivamus at lorem eget augue rhoncus varius. Curabitur hendrerit, nibh ut sagittis ultrices,
    ipsum elit tempus arcu, ac ullamcorper metus magna in lacus. Morbi elementum imperdiet magna in ultrices. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed fermentum leo, ac cursus sapien. Proin neque nisi, tempor vel massa et, consectetur
    eleifend sem.
  </p>
  <p>
    Aliquam erat volutpat. Donec lectus velit, rhoncus non euismod in, scelerisque sed libero. Nunc et neque est. Nam viverra ac quam interdum auctor. Nulla sed lacus mauris. Proin sit amet ultricies lorem. Vestibulum ante ipsum primis in faucibus orci luctus
    et ultrices posuere cubilia Curae; In hac habitasse platea dictumst. Nulla sed cursus neque.
  </p>
  <p>
    Curabitur blandit ipsum fermentum mauris consequat, ut feugiat nisl consequat. Nullam sit amet commodo diam. Etiam fringilla felis et augue mattis, sed dapibus massa tristique. Mauris ut nisi eget ex faucibus hendrerit. Mauris ut nisi nulla. Aenean et
    urna dolor. Aenean consectetur metus urna, a mattis orci pretium nec. Pellentesque non augue magna. In accumsan nisl tellus, id porttitor nisi feugiat eu. Curabitur eleifend urna ac augue congue tincidunt.
  </p>
</div>

But the <canvas> element only renders a pixel image, not an HTML element which means that the content won't be selectable anymore, links will be broken etc...* and that you will face html2canvas' limitations. * Note that you may be able to workaround those with a lot of calculations

An other solution, if you don't really need to have this effect on the content would be to fake it, using CSS radial-gradients and a border-radius, as proposed by James Holderness in this answer:

var div = document.querySelector('div');
var pt=-100;
function animBG(){
	pt=((pt+101)%300)-100;
	div.style.backgroundImage= 'radial-gradient(ellipse at '+pt+'% '+pt+'% , rgb(255, 255, 255) 0%, rgb(214, 214, 214) 45%, rgb(174, 176, 173) 58%)';
	requestAnimationFrame(animBG)
	}
animBG();
div {
		  height: 600px;
		  width: 600px;
		  border-radius: 100%;
		  background: transparent radial-gradient(ellipse at 30% 20%, rgb(255, 255, 255) 0%, rgb(214, 214, 214) 45%, rgb(174, 176, 173) 58%) repeat scroll 0% 0%;
		  text-align: center;
		  position: relative;
          box-shadow: inset 0px 0px 15px rgba(60,60,60,.5);
		}
		div>p {
		  width: 344px;
		  position: absolute;
		  top: 50%;
		  left: 50%;
		  -webkit-transform: translate(-50%, -50%);
		  transform: translate(-50%, -50%);
		  color: rgba(0, 0, 0, .7)
		}
<div>


  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet bibendum augue, nec convallis enim bibendum non. Donec sagittis finibus lorem nec porttitor. Donec vel tincidunt ante. Praesent semper luctus arcu, at eleifend nibh dapibus sit
    amet. Aenean maximus ex in luctus bibendum. Nullam in ligula quis tellus convallis rutrum. Vivamus id placerat metus. Morbi efficitur sem at cursus bibendum. Ut fermentum odio in lectus posuere accumsan. Etiam imperdiet metus at ornare tempus. Suspendisse
    nulla metus, aliquam viverra elementum sed, consequat ac est. Sed lorem neque, finibus ac ultricies vel, ullamcorper ut nibh. Praesent est nulla, dictum eu commodo nec, sollicitudin condimentum ante.
  </p>

</div>

Upvotes: 1

Soeb Safi
Soeb Safi

Reputation: 341

In that case css transitions will help, have a look at link this way you can resize div from left to right and in whatever direction you want. Or else if you want to animate the div like you want the div to move from one place to another use @keyframe in css

Upvotes: 0

Related Questions