Анимированное солнце со спутником вращающимся по орбите
У меня задача анимировать солнце.
Нужно, чтобы были всполохи и небольшие лучики. Лучики должны гореть, как пламя и медленно вращаться.
Технологии могут быть любые: SVG, SMIL, JavaScript, CSS, Canvas, WebGl, или что-то ещё.
Так же необходимо сделать одну планету вращающуюся вокруг солнца. Планета должна вращаться по такой орбите, чтобы она часть пути пролетала за солнцем.
Подскажите пожалуйста, как такое можно сделать?
Принимаются ответы также с частичным решением. Например: без планеты или без лучиков.
Всего должно быть 3 элемента анимации.
- Всполохи.
- Лучики как огонь. Должны а) гореть б) Вращаться покругу.
- Вращающаяся планета, где часть орбиты проходит за солнцем.
PS: Постараюсь подготовить своё решение, если смогу.
Ответы (7 шт):
Размумеется что не моё: codepen
var gl;
var pwgl = {};
pwgl.ongoingImageLoads = [];
var canvas;
// Variables for interactive control
var transY = 0,
transZ = 0;
var xRot = yRot = zRot = xOffs = yOffs = drag = 0;
pwgl.listOfPressedKeys = [];
var lastTime = 0;
// Keep track of pressed down keys in a list
function createGLContext(canvas) {
var names = ["webgl", "experimental-webgl"];
var context = null;
for (var i = 0; i < names.length; i++) {
try {
context = canvas.getContext(names[i]);
} catch (e) {}
if (context) {
break;
}
}
if (context) {
context.viewportWidth = canvas.width;
context.viewportHeight = canvas.height;
} else {
alert("Failed to create WebGL context!");
}
return context;
}
var vertexShaderSrc =
"attribute vec3 aVertexPosition;" +
"attribute vec3 aVertexNormal;" +
"attribute vec2 aTextureCoordinates;" +
"uniform mat4 uMVMatrix;" +
"uniform mat4 uPMatrix;" +
"uniform mat3 uNMatrix;" +
"varying vec2 vTextureCoord;" +
"varying vec3 vNormalEye;" +
"varying vec3 vPositionEye3;" +
"void main() {" +
// Get vertex position in eye coordinates and send to the fragment shader
"vec4 vertexPositionEye4 = uMVMatrix * vec4(aVertexPosition, 1.0);" +
"vPositionEye3 = vertexPositionEye4.xyz / vertexPositionEye4.w;" +
// Transform the normal to eye coordinates and send to fragment shader
"vNormalEye = normalize(uNMatrix * aVertexNormal);" +
// Transform the geometry
"gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);" +
"vTextureCoord = aTextureCoordinates;" +
"}";
var fragmentShaderSrc =
"precision mediump float;" +
"varying vec2 vTextureCoord;" +
"varying vec3 vNormalEye;" +
"varying vec3 vPositionEye3;" +
"uniform vec3 uAmbientLightColor;" +
"uniform vec3 uDiffuseLightColor;" +
"uniform vec3 uSpecularLightColor;" +
"uniform vec3 uLightPosition;" +
"uniform vec3 uSpotDirection;" +
"uniform sampler2D uSampler;" +
"const float shininess = 5.0;" +
"const float spotExponent = 80.0;" +
// cutoff angle of spot light
"const float spotCosCutoff = 0.97;" + // corresponds to 14 degrees
"vec3 lightWeighting = vec3(0.0, 0.0, 0.0);" +
"void main() {" +
// Calculate the vector (L) to the light source.
"vec3 vectorToLightSource = normalize(uLightPosition - vPositionEye3);" +
// Calculate N dot L for diffuse lighting
"float diffuseLightWeighting = max(dot(vNormalEye," +
"vectorToLightSource), 0.0);" +
// Only do spot and specular light calculations if we have diffuse light term.
"if (diffuseLightWeighting > 0.0) {" +
"float spotEffect = dot(normalize(uSpotDirection)," +
"normalize(-vectorToLightSource));" +
"if (spotEffect > spotCosCutoff) {" +
"spotEffect = pow(spotEffect, spotExponent);" +
"vec3 reflectionVector = normalize(reflect(-" +
"vectorToLightSource,vNormalEye));" +
// Calculate view vector (V)
"vec3 viewVectorEye = -normalize(vPositionEye3);" +
"float rdotv = max(dot(reflectionVector, viewVectorEye), 0.0);" +
"float specularLightWeighting = pow(rdotv, shininess);" +
"lightWeighting =" +
"spotEffect * uDiffuseLightColor * diffuseLightWeighting +" +
"spotEffect * uSpecularLightColor * specularLightWeighting;" +
"}" +
"}" +
// Add the ambient light
"lightWeighting += uAmbientLightColor;" +
"vec4 texelColor = texture2D(uSampler, vTextureCoord);" +
// Modulate texel color with lightweighting and write as final color
"gl_FragColor = vec4(lightWeighting.rgb * texelColor.rgb, texelColor.a);" +
"}";
function setupShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders " + gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
pwgl.vertexPositionAttributeLoc = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(pwgl.vertexPositionAttributeLoc);
pwgl.vertexTextureAttributeLoc = gl.getAttribLocation(shaderProgram, "aTextureCoordinates");
gl.enableVertexAttribArray(pwgl.vertexTextureAttributeLoc);
pwgl.vertexNormalAttributeLoc = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(pwgl.vertexNormalAttributeLoc);
pwgl.uniformProjMatrixLoc = gl.getUniformLocation(shaderProgram, "uPMatrix");
pwgl.uniformMVMatrixLoc = gl.getUniformLocation(shaderProgram, "uMVMatrix");
pwgl.uniformNormalMatrixLoc = gl.getUniformLocation(shaderProgram, "uNMatrix");
pwgl.uniformSamplerLoc = gl.getUniformLocation(shaderProgram, "uSampler");
pwgl.uniformLightPositionLoc = gl.getUniformLocation(shaderProgram,
"uLightPosition");
pwgl.uniformAmbientLightColorLoc = gl.getUniformLocation(shaderProgram,
"uAmbientLightColor");
pwgl.uniformDiffuseLightColorLoc = gl.getUniformLocation(shaderProgram,
"uDiffuseLightColor");
pwgl.uniformSpecularLightColorLoc = gl.getUniformLocation(shaderProgram,
"uSpecularLightColor");
pwgl.uniformSpotDirectionLoc = gl.getUniformLocation(shaderProgram, "uSpotDirection");
pwgl.modelViewMatrix = mat4.create();
pwgl.modelViewMatrixStack = [];
pwgl.projectionMatrix = mat4.create();
}
function setupTextures() {
// Texture for the Earth
pwgl.earthTexture = gl.createTexture();
loadImageForTexture("https://raw.githubusercontent.com/josh-street/webgl-earthsatellite/master/earth.jpg", pwgl.earthTexture);
// Texture for the satellite
pwgl.satelliteTexture = gl.createTexture();
loadImageForTexture("https://raw.githubusercontent.com/josh-street/webgl-earthsatellite/master/satellite.png", pwgl.satelliteTexture);
}
function loadImageForTexture(url, texture) {
var image = new Image();
image.crossOrigin = '';
image.onload = function() {
pwgl.ongoingImageLoads.splice(pwgl.ongoingImageLoads.indexOf(image), 1);
textureFinishedLoading(image, texture);
}
pwgl.ongoingImageLoads.push(image);
image.src = url;
}
function textureFinishedLoading(image, texture) {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
gl.bindTexture(gl.TEXTURE_2D, null);
}
function setupLights() {
gl.uniform3fv(pwgl.uniformLightPositionLoc, [0.0, 500.0, -16.0]);
gl.uniform3fv(pwgl.uniformSpotDirectionLoc, [0.0, -1.0, 0.0]);
gl.uniform3fv(pwgl.uniformAmbientLightColorLoc, [0.2, 0.2, 0.2]);
gl.uniform3fv(pwgl.uniformDiffuseLightColorLoc, [0.7, 0.7, 0.7]);
gl.uniform3fv(pwgl.uniformSpecularLightColorLoc, [0.8, 0.8, 0.8]);
}
function pushModelViewMatrix() {
var copyToPush = mat4.create(pwgl.modelViewMatrix);
pwgl.modelViewMatrixStack.push(copyToPush);
}
function popModelViewMatrix() {
if (pwgl.modelViewMatrixStack.length == 0) {
throw "Error popModelViewMatrix() - Stack was empty ";
}
pwgl.modelViewMatrix = pwgl.modelViewMatrixStack.pop();
}
function uploadNormalMatrixToShader() {
var normalMatrix = mat3.create();
mat4.toInverseMat3(pwgl.modelViewMatrix, normalMatrix);
mat3.transpose(normalMatrix);
gl.uniformMatrix3fv(pwgl.uniformNormalMatrixLoc, false, normalMatrix);
}
function uploadModelViewMatrixToShader() {
gl.uniformMatrix4fv(pwgl.uniformMVMatrixLoc, false,
pwgl.modelViewMatrix);
}
function uploadProjectionMatrixToShader() {
gl.uniformMatrix4fv(pwgl.uniformProjMatrixLoc, false,
pwgl.projectionMatrix);
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
var mouseDown = false;
var lastMouseX = null;
var lastMouseY = null;
var earthRotationMatrix = mat4.create();
mat4.identity(earthRotationMatrix);
var earthVertexPositionBuffer;
var earthVertexNormalBuffer;
var earthVertexTextureCoordBuffer;
var earthVertexIndexBuffer;
function setupEarthBuffers() {
var latitudeBands = 60;
var longitudeBands = 60;
var radius = 5;
var vertexPositionData = [];
var normalData = [];
var textureCoordData = [];
for (var latNumber = 0; latNumber <= latitudeBands; latNumber++) {
var theta = latNumber * Math.PI / latitudeBands;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
for (var longNumber = 0; longNumber <= longitudeBands; longNumber++) {
var phi = longNumber * 2 * Math.PI / longitudeBands;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * sinTheta;
var y = cosTheta;
var z = sinPhi * sinTheta;
var u = 1 - (longNumber / longitudeBands);
var v = 1 - (latNumber / latitudeBands);
normalData.push(x);
normalData.push(y);
normalData.push(z);
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(radius * x);
vertexPositionData.push(radius * y);
vertexPositionData.push(radius * z);
}
}
var indexData = [];
for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
indexData.push(first);
indexData.push(second);
indexData.push(first + 1);
indexData.push(second);
indexData.push(second + 1);
indexData.push(first + 1);
}
}
earthVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
earthVertexNormalBuffer.itemSize = 3;
earthVertexNormalBuffer.numItems = normalData.length / 3;
earthVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
earthVertexTextureCoordBuffer.itemSize = 2;
earthVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
earthVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
earthVertexPositionBuffer.itemSize = 3;
earthVertexPositionBuffer.numItems = vertexPositionData.length / 3;
earthVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, earthVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);
earthVertexIndexBuffer.itemSize = 1;
earthVertexIndexBuffer.numItems = indexData.length;
}
function setupSatelliteBuffers() {
pwgl.satelliteVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexPositionBuffer);
var satelliteVertexPosition = [
// Front face
1.0, 1.0, 1.0, //v0
-1.0, 1.0, 1.0, //v1
-1.0, -1.0, 1.0, //v2
1.0, -1.0, 1.0, //v3
// Back face
1.0, 1.0, -1.0, //v4
-1.0, 1.0, -1.0, //v5
-1.0, -1.0, -1.0, //v6
1.0, -1.0, -1.0, //v7
// Left face
-1.0, 1.0, 1.0, //v8
-1.0, 1.0, -1.0, //v9
-1.0, -1.0, -1.0, //v10
-1.0, -1.0, 1.0, //v11
// Right face
1.0, 1.0, 1.0, //12
1.0, -1.0, 1.0, //13
1.0, -1.0, -1.0, //14
1.0, 1.0, -1.0, //15
// Top face
1.0, 1.0, 1.0, //v16
1.0, 1.0, -1.0, //v17
-1.0, 1.0, -1.0, //v18
-1.0, 1.0, 1.0, //v19
// Bottom face
1.0, -1.0, 1.0, //v20
1.0, -1.0, -1.0, //v21
-1.0, -1.0, -1.0, //v22
-1.0, -1.0, 1.0, //v23
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(satelliteVertexPosition),
gl.STATIC_DRAW);
pwgl.CUBE_VERTEX_POS_BUF_ITEM_SIZE = 3;
pwgl.CUBE_VERTEX_POS_BUF_NUM_ITEMS = 24;
// Setup buffer with index
pwgl.satelliteVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.satelliteVertexIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 6, 5, 4, 7, 6, // Back face
8, 9, 10, 8, 10, 11, // Left face
12, 13, 14, 12, 14, 15, // Right face
16, 17, 18, 16, 18, 19, // Top face
20, 22, 21, 20, 23, 22 // Bottom face
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
pwgl.CUBE_VERTEX_INDEX_BUF_ITEM_SIZE = 1;
pwgl.SATELLITE_VERTEX_INDEX_BUF_NUM_ITEMS = 36;
// Setup buffer with texture coordinates
pwgl.satelliteVertexTextureCoordinateBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexTextureCoordinateBuffer);
var textureCoordinates = [
//Front face
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
// Back face
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
// Left face
1.0, 1.0,
1.0, 1.0,
1.0, 1.0,
1.0, 1.0,
// Right face
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
// Top face
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
// Bottom face
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
pwgl.CUBE_VERTEX_TEX_COORD_BUF_ITEM_SIZE = 2;
pwgl.CUBE_VERTEX_TEX_COORD_BUF_NUM_ITEMS = 24;
// Specify normals to be able to do lighting calculations
pwgl.satelliteVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexNormalBuffer);
var satelliteVertexNormals = [
// Front face
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
// Back face
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
// Left face
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
// Right face
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
// Top face
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
// Bottom face
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(satelliteVertexNormals),
gl.STATIC_DRAW);
pwgl.CUBE_VERTEX_NORMAL_BUF_ITEM_SIZE = 3;
pwgl.CUBE_VERTEX_NORMAL_BUF_NUM_ITEMS = 24;
}
function setupBuffers() {
setupEarthBuffers();
setupSatelliteBuffers();
}
function drawSatellite(texture) {
// Bind position buffer
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexPositionBuffer);
gl.vertexAttribPointer(pwgl.vertexPositionAttributeLoc,
pwgl.CUBE_VERTEX_POS_BUF_ITEM_SIZE,
gl.FLOAT, false, 0, 0);
// Bind normal buffer
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexNormalBuffer);
gl.vertexAttribPointer(pwgl.vertexNormalAttributeLoc,
pwgl.CUBE_VERTEX_NORMAL_BUF_ITEM_SIZE,
gl.FLOAT, false, 0, 0);
// bind texture coordinate buffer
gl.bindBuffer(gl.ARRAY_BUFFER, pwgl.satelliteVertexTextureCoordinateBuffer);
gl.vertexAttribPointer(pwgl.vertexTextureAttributeLoc,
pwgl.CUBE_VERTEX_TEX_COORD_BUF_ITEM_SIZE,
gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
// Bind index buffer and draw cube
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pwgl.satelliteVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, pwgl.SATELLITE_VERTEX_INDEX_BUF_NUM_ITEMS,
gl.UNSIGNED_SHORT, 0);
}
function drawEarth(texture) {
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexPositionBuffer);
gl.vertexAttribPointer(pwgl.vertexPositionAttributeLoc, earthVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexNormalBuffer);
gl.vertexAttribPointer(pwgl.vertexNormalAttributeLoc, earthVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, earthVertexTextureCoordBuffer);
gl.vertexAttribPointer(pwgl.vertexTextureAttributeLoc, earthVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, earthVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, earthVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
var newAngle = 0;
function draw() {
pwgl.requestId = requestAnimFrame(draw);
var currentTime = Date.now();
handlePressedDownKeys();
// Update FPS if a second or more has passed since last FPS update
if (currentTime - pwgl.previousFrameTimeStamp >= 1000) {
pwgl.fpsCounter.innerHTML = pwgl.nbrOfFramesForFPS;
pwgl.nbrOfFramesForFPS = 0;
pwgl.previousFrameTimeStamp = currentTime;
}
mat4.translate(pwgl.modelViewMatrix, [0.0, transY, transZ],
pwgl.modelViewMatrix);
mat4.rotateX(pwgl.modelViewMatrix, xRot / 50, pwgl.modelViewMatrix);
mat4.rotateY(pwgl.modelViewMatrix, yRot / 50, pwgl.modelViewMatrix);
yRot = xRot = zRot = transY = transZ = 0;
uploadModelViewMatrixToShader();
uploadProjectionMatrixToShader();
uploadNormalMatrixToShader();
gl.uniform1i(pwgl.uniformSamplerLoc, 0);
pushModelViewMatrix();
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
newAngle += (90 * elapsed) / 1000;
}
lastTime = timeNow;
var rotationSpeed = -degToRad(newAngle) / 50; // Sets earth rotation speed
mat4.rotateY(pwgl.modelViewMatrix, rotationSpeed, pwgl.modelViewMatrix);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
drawEarth(pwgl.earthTexture);
popModelViewMatrix();
pushModelViewMatrix();
if (currentTime === undefined) {
currentTime = Date.now();
}
if (pwgl.animationStartTime === undefined) {
pwgl.animationStartTime = currentTime;
}
pwgl.angle = (currentTime - pwgl.animationStartTime) / pwgl.orbitalMultipler * 2 * Math.PI %
(2 * Math.PI);
pwgl.x = Math.cos(pwgl.angle) * pwgl.circleRadius;
pwgl.z = Math.sin(pwgl.angle) * pwgl.circleRadius;
mat4.translate(pwgl.modelViewMatrix, [pwgl.x, pwgl.y, pwgl.z],
pwgl.modelViewMatrix);
mat4.scale(pwgl.modelViewMatrix, [0.5, 0.5, 0.5], pwgl.modelViewMatrix);
// CRUDE NOT WORKING FULLY
pwgl.satRotation = -degToRad(newAngle) * pwgl.satMultiplier;
mat4.rotateY(pwgl.modelViewMatrix, pwgl.satRotation, pwgl.modelViewMatrix);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
uploadProjectionMatrixToShader();
drawSatellite(pwgl.satelliteTexture);
popModelViewMatrix();
pwgl.nbrOfFramesForFPS++;
}
function startup() {
var canvas = document.getElementById("glcanvas");
canvas = WebGLDebugUtils.makeLostContextSimulatingCanvas(canvas);
canvas.addEventListener('webglcontextlost', handleContextLost, false);
canvas.addEventListener('webglcontextrestored', handleContextRestored,
false);
document.addEventListener('keydown', handleKeyDown, false);
document.addEventListener('keyup', handleKeyUp, false);
canvas.addEventListener('mousemove', mymousemove, false);
canvas.addEventListener('mousedown', mymousedown, false);
canvas.addEventListener('mouseup', mymouseup, false);
canvas.addEventListener('mousewheel', wheelHandler, false);
canvas.addEventListener('DOMMouseScroll', wheelHandler, false);
gl = createGLContext(canvas);
pwgl.fpsCounter = document.getElementById("fps");
init();
draw();
}
var relation = 1.6 / 2500;
function init() {
// Initialization that is performed during first startup and when the
// event webglcontextrestored is received is included in this function.
setupShaders();
setupBuffers();
setupLights();
setupTextures();
// Transparent canvas for space background image
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.enable(gl.DEPTH_TEST);
pwgl.x = 0.0;
pwgl.y = 0.0;
pwgl.z = 0.0;
pwgl.circleRadius = 10.0;
pwgl.orbitalMultipler = 2000;
pwgl.satMultiplier = 2;
// Initialize some variables related to the animation
pwgl.animationStartTime = undefined;
pwgl.nbrOfFramesForFPS = 0;
pwgl.previousFrameTimeStamp = Date.now();
mat4.perspective(30, gl.viewportWidth / gl.viewportHeight, 1, 100.0, pwgl.projectionMatrix);
mat4.identity(pwgl.modelViewMatrix);
mat4.lookAt([0, 0, 50], [0, 0, 0], [0, 1, 0], pwgl.modelViewMatrix);
}
function handleContextLost(event) {
event.preventDefault();
cancelRequestAnimFrame(pwgl.requestId);
// Ignore all ongoing image loads by removing their onload handler
for (var i = 0; i < pwgl.ongoingImageLoads.length; i++) {
pwgl.ongoingImageLoads[i].onload = undefined;
}
pwgl.ongoingImageLoads = [];
}
function handleContextRestored(event) {
init();
pwgl.requestId = requestAnimFrame(draw, canvas);
}
function handleKeyDown(event) {
pwgl.listOfPressedKeys[event.keyCode] = true;
}
function handleKeyUp(event) {
pwgl.listOfPressedKeys[event.keyCode] = false;
}
function handlePressedDownKeys() {
if (pwgl.listOfPressedKeys[38]) {
// Arrow up, increase radius of circle
if (pwgl.circleRadius < 50) {
pwgl.circleRadius += 0.1;
} else {
pwgl.circleRadius = 20;
}
}
if (pwgl.listOfPressedKeys[40]) {
// Arrow down, decrease radius of circle
pwgl.circleRadius -= 0.1;
if (pwgl.circleRadius > 6) {
pwgl.circleRadius -= 0.1
} else {
pwgl.circleRadius = 6;
}
}
if (pwgl.listOfPressedKeys[37]) {
// Left Arrow, speed up orbital speed
pwgl.orbitalMultipler -= 20;
var x = pwgl.orbitalMultipler * relation;
var y = 1.6 - x;
pwgl.satMultiplier = 1.6 + y;
if (pwgl.orbitalMultipler < 250) {
pwgl.orbitalMultipler = 250
}
}
if (pwgl.listOfPressedKeys[39]) {
// Right Arrow, slow down orbital speed
pwgl.orbitalMultipler += 50;
var x = pwgl.orbitalMultipler * relation;
var y = 1.6 - x;
pwgl.satMultiplier = 1.6 + y;
console.log(pwgl.satMultiplier);
if (pwgl.orbitalMultipler > 20000) {
pwgl.orbitalMultipler = 20000;
}
}
}
function mymousedown(ev) {
drag = 1;
xOffs = ev.clientX;
yOffs = ev.clientY;
}
function mymouseup(ev) {
drag = 0;
}
function mymousemove(ev) {
if (drag == 0) return;
if (ev.shiftKey) {
transZ = (ev.clientY - yOffs) / 10;
} else if (ev.altKey) {
transY = -(ev.clientY - yOffs) / 10;
} else {
yRot = -xOffs + ev.clientX;
xRot = -yOffs + ev.clientY;
}
xOffs = ev.clientX;
yOffs = ev.clientY;
}
function wheelHandler(ev) {
if (ev.altKey) transY = -ev.detail / 10;
else transZ = ev.detail / 10;
ev.preventDefault();
}
body {
background-image: url("https://raw.githubusercontent.com/josh-street/webgl-earthsatellite/master/bg.jpg");
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
font-size: 9pt;
}
p {
color: #fff;
line-height: 0.7;
}
li {
color: #fff;
line-height: 1.3;
}
h1 {
font-size: 12pt;
color: #fff;
margin-left: 10px;
}
#fps-counter {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
display: inline-block;
text-align: right;
color: #fff;
}
#glcanvas {
background-image: url("https://raw.githubusercontent.com/josh-street/webgl-earthsatellite/master/bg.jpg");
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
margin: 0px;
z-index: -1;
position: fixed;
}
#hide1 {
display: none;
}
#hide2 {
display: none;
}
#instructions {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
padding-left: 5px;
background: rgba(255, 255, 255, 0);
width: 24%;
height: 12em;
border-radius: 5px;
z-index: 0;
}
<body onload="startup()">
<canvas id="glcanvas" style="border: none;" width="1400" height="800"></canvas>
<div id="fps-counter">
<p> FPS: <span id="fps">--</span>
<p>
</div>
<script src="https://cdn.rawgit.com/josh-street/webgl-earthsatellite/master/glMatrix.js"></script>
<script src="https://cdn.rawgit.com/josh-street/webgl-earthsatellite/master/webgl/webgl-debug.js"></script>
<script src="https://cdn.rawgit.com/josh-street/webgl-earthsatellite/master/webgl/webgl-utils.js"></script>
</body>
Вариант 1
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #010101;
min-height: 100vh;
}
.system {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(75deg);
}
.sun,
.orbit,
.planet {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
border-radius: 50%;
}
.sun,
.planet {
width: 2em;
height: 2em;
margin-top: -1em;
margin-left: -1em;
}
.sun {
font-size: 7em;
background: linear-gradient(to bottom, #F8E82F 0%, rgba(251, 65, 9, 1) 100%);
box-shadow: 0 0 60px rgba(255, 160, 60, .4);
transform: rotateX(-90deg);
}
.orbit {
width: 24em;
height: 24em;
margin-top: -12em;
margin-left: -12em;
border: 1px solid rgba(255, 255, 255, .25);
animation: animOrbit 12s linear infinite;
}
.planet {
background-color: aliceblue;
left: 100%;
animation: animPlanet 12s linear infinite;
}
@keyframes animOrbit {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(-360deg);
}
}
@keyframes animPlanet {
0% {
transform: rotateX(-90deg) rotateY(360deg) rotateZ(0deg);
}
100% {
transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg);
}
}
<div class="system">
<div class="sun"></div>
<div class="orbit">
<div class="planet"></div>
</div>
</div>
Вариант 2
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #010101;
min-height: 100vh;
overflow: hidden;
}
.system {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(65deg) rotateY(-65deg);
animation: animSystem 36s linear infinite;
}
@keyframes animSystem{
0%{
transform: rotateX(65deg) rotateY(0deg);
}
100%{
transform: rotateX(65deg) rotateY(-360deg);
}
}
.sun,
.orbit,
.planet {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
border-radius: 50%;
}
.sun,
.planet {
width: 2em;
height: 2em;
margin-top: -1em;
margin-left: -1em;
}
.sun {
font-size: 7em;
background-color: #FB7209;
background: linear-gradient(to bottom, #F8E82F 0%, rgba(251, 65, 9, 1) 100%);
background-size: cover;
transform: rotateX(-90deg);
box-shadow:
0 0 10px 5px rgba(244, 110, 28, .6),
0 0 20px 10px rgba(244, 110, 28, .3),
0 0 30px 15px rgba(244, 110, 28, .1);
animation: animSunFire 6s alternate infinite;
}
@keyframes animSunFire {
0%,
100% {
box-shadow:
0 0 10px 5px rgba(244, 110, 28, .6),
0 0 20px 10px rgba(244, 110, 28, .3),
0 0 30px 15px rgba(244, 110, 28, .1);
}
50% {
box-shadow:
0 0 14px 7px rgba(244, 110, 28, .6),
0 0 28px 14px rgba(244, 110, 28, .3),
0 0 42px 81px rgba(244, 110, 28, .1);
}
}
.orbit {
width: 24em;
height: 24em;
margin-top: -12em;
margin-left: -12em;
border: 4px solid rgba(255, 255, 255, .25);
animation: animOrbit 12s linear infinite;
}
.planet {
background-color: aliceblue;
left: 100%;
animation: animPlanet 12s linear infinite;
}
@keyframes animOrbit {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(-360deg);
}
}
@keyframes animPlanet {
0% {
transform: rotateX(-90deg) rotateY(360deg) rotateZ(0deg);
}
100% {
transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg);
}
}
<div class="system">
<div class="sun"></div>
<div class="orbit">
<div class="planet"></div>
</div>
</div>
Объяснения смотрите в комментариях к коду.
Осторожно! При запуске анимации включается трек группы Zodiac
UPDATE
Добавлена анимация вращения планеты вокруг своей оси
.flame {
transform-origin: center;
transform-box:fill-box;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 10 200 200" >
<defs>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="2" />
</filter>
<!-- Анимация градиента языков пламени -->
<radialGradient id="gradSun">
<stop offset="20%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;40%;10%;80%" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;#FF6200;gold" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
</radialGradient>
<!-- Градиент окраски вращающейся планеты -->
<linearGradient id="gradEarth">
<stop offset="0%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- Фон -->
<rect width="100%" height="100%" fill="#321300" />
<g id="btn1" onclick='play()' transform="translate(0 0)" >
<circle cx="180" cy="185" r="8" fill="url(#gradEarth)" />
<text id="txt1" x="150" y="170" font-size="1.2rem" fill="gold" >Start</text>
</g>
<!-- Протуберанцы солнца -->
<path id="flame" class="flame" fill="url(#gradSun)" filter="url(#dropShadow2)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" >
<!-- Анимация роста, уменьшения Протуберанцев солнца -->
<animateTransform attributeName="transform" type="scale" begin="btn1.click" dur="6s" values="0.7;1;0.8;1;0.7;0.7" repeatCount="indefinite" />
</path>
<!-- Орбита вращения планеты -->
<path id="orbita" transform="translate(-1,0)" d="m77.6 69.4c3.3-5.1 7.3-9.8 11.4-14.4 4.5-5.1 9.2-10.2 14.4-14.7 3.8-3.3 7.9-6.5 12.3-9 3.9-2.2 7.9-4.4 12.3-5.1 4.6-0.7 9.8-1 13.8 1.2 4.4 2.4 7.3 7.3 9 12 2.1 5.6 1.8 12 1.2 18-0.3 2.8-1.1 5.5-2.1 8.1-7.8 21.2-17.1 42.2-29.4 61.1-9.3 14.3-20.1 27.8-33 39-2.9 2.6-6.3 4.7-9.9 6.3-3.5 1.5-7.3 2.9-11.1 3-3.7 0.1-7.8 0-10.8-2.1-4.2-2.9-6.8-8-8.1-12.9-2-7.3-0.6-15.3 0.6-22.8 1.4-8.7 4.2-17.3 7.5-25.5 5.9-14.7 13.3-28.9 21.9-42.2z" style="fill:none;stroke:grey; stroke-width:2"/>
<!-- Правая половинка солнца -->
<path id="sunR" fill="#FF6600" d="m106.4 38.5c-6.3 4.8-12.1 10.7-15.5 14.9-5.5 6.6-11.7 13.6-16.5 21.1-6.1 9.6-10.8 20-15.4 30.4-3.3 7.4-6.5 14.8-8.6 22.6-1.3 4.6-2.7 9.5-2.4 14.1 0.4 5.8 12.4 13.2 20.4 17.1 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-8.6-32.4-19.8-44-9-9.3-31.3-20-34.8-17.4z" />
<!-- Левая половинка солнца -->
<path id="sunL" fill="#FF6600" d="m45.8 140.1c1.6-8.4 1.9-10.1 3.3-15.1 1.5-5.4 3.2-10.8 5.2-16 2.6-6.7 5.8-13.1 9.1-19.5 3.1-5.9 6.6-11.7 10.3-17.2 3.6-5.4 7.3-10.8 11.5-15.7 5.4-6.3 12.6-13.1 17.5-17.8 4.2-4.1-29.9 1.1-41.5 9.3-23.1 16.4-27.9 35.8-28.9 52-0.4 7.1 1.1 15.8 3.7 23.2 2.1 6.1 9.3 18.6 9.6 16.9z" />
<!-- Анимация вращения планеты -->
<circle cx="0" cy="0" r="12" fill="url(#gradEarth)" >
<animateMotion begin="btn1.click" dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbita" />
</animateMotion>
<!-- Анимация вращения планеты вокруг своей оси -->
<animateTransform attributeName="transform" type="rotate" dur="1.5s" begin="btn1.click" values="0 0 0;360 0 0 " repeatCount="indefinite" />
</circle>
<!-- Дополнительная маскирующая зона солнца, чтобы не было видно вращения планеты с обратной строны солнца -->
<path id="sunR2" fill="#FF6600" d="m112.1 49.9c-6.3 4.8-8.2 7.1-11.6 11.3-5.5 6.6-10.3 12.7-14.7 19.6-5.5 8.7-10.2 18-14.5 27.4-3.2 7.2-5.7 14.6-8.3 22-2.2 6.2-6.3 14.3-6 18.9 0.4 5.8 6.9 7.4 11.4 9.6 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-7.2-34-19.8-44-7.7-6.2-25.6-8.6-29.1-6z" />
</svg>
<script>
var zodiac = new Audio();
zodiac.src = 'https://svg-art.ru/files/zodiac.mp3';
function play() {
zodiac.play();
}
</script>
Вариант #2
C использование вращения одного слоя паттерна языков пламени и применение фильтра feTurbulence для создания колыхания протуберанцев солнца
Вращение паттерна:
.flame {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun 40s linear infinite;
}
@keyframes rotate-sun {
0% {transform: rotateX(0deg); }
100% {transform: rotateZ(360deg); }
}
Применение анимации фильтра feTurbulence
Настраивая значения baseFrequency, numOctaves,scale="25" добейтесь эффекта колыхания пламени по своему вкусу.
<!-- Эффект колыхания огня для протуберанцов солнца -->
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0005" numOctaves="5" result="turbulence" >
<animate attributeName="baseFrequency" dur="32s" values="0.0005;0.02;0.0005;0.02;0.0005" begin="btn1.click" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
.flame {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun 40s linear infinite;
}
@keyframes rotate-sun {
0% {transform: rotateX(0deg); }
100% {transform: rotateZ(360deg); }
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 10 200 200" >
<defs>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="2" />
</filter>
<!-- Эффект колыхания огня для протуберанцов солнца -->
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0005" numOctaves="5" result="turbulence" >
<animate attributeName="baseFrequency" dur="32s" values="0.0005;0.02;0.0005;0.02;0.0005" begin="btn1.click" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
<!-- Анимация градиента языков пламени -->
<radialGradient id="gradSun">
<stop offset="20%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;40%;10%;80%" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;#FF6200;gold" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
</radialGradient>
<!-- Градиент окраски вращающейся планеты -->
<linearGradient id="gradEarth">
<stop offset="40%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- Фон -->
<rect width="100%" height="100%" fill="#321300" />
<!-- Протуберанцы солнца 1-ая группа -->
<path id="flame" class="flame" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" >
</path>
<!-- Орбита вращения планеты -->
<path id="orbita" transform="translate(-1,0)" d="m77.6 69.4c3.3-5.1 7.3-9.8 11.4-14.4 4.5-5.1 9.2-10.2 14.4-14.7 3.8-3.3 7.9-6.5 12.3-9 3.9-2.2 7.9-4.4 12.3-5.1 4.6-0.7 9.8-1 13.8 1.2 4.4 2.4 7.3 7.3 9 12 2.1 5.6 1.8 12 1.2 18-0.3 2.8-1.1 5.5-2.1 8.1-7.8 21.2-17.1 42.2-29.4 61.1-9.3 14.3-20.1 27.8-33 39-2.9 2.6-6.3 4.7-9.9 6.3-3.5 1.5-7.3 2.9-11.1 3-3.7 0.1-7.8 0-10.8-2.1-4.2-2.9-6.8-8-8.1-12.9-2-7.3-0.6-15.3 0.6-22.8 1.4-8.7 4.2-17.3 7.5-25.5 5.9-14.7 13.3-28.9 21.9-42.2z" style="fill:none;stroke:grey; stroke-width:2"/>
<!-- Правая половинка солнца -->
<path id="sunR" fill="#FF6600" d="m106.4 38.5c-6.3 4.8-12.1 10.7-15.5 14.9-5.5 6.6-11.7 13.6-16.5 21.1-6.1 9.6-10.8 20-15.4 30.4-3.3 7.4-6.5 14.8-8.6 22.6-1.3 4.6-2.7 9.5-2.4 14.1 0.4 5.8 12.4 13.2 20.4 17.1 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-8.6-32.4-19.8-44-9-9.3-31.3-20-34.8-17.4z" />
<!-- Левая половинка солнца -->
<path id="sunL" fill="#FF6600" d="m45.8 140.1c1.6-8.4 1.9-10.1 3.3-15.1 1.5-5.4 3.2-10.8 5.2-16 2.6-6.7 5.8-13.1 9.1-19.5 3.1-5.9 6.6-11.7 10.3-17.2 3.6-5.4 7.3-10.8 11.5-15.7 5.4-6.3 12.6-13.1 17.5-17.8 4.2-4.1-29.9 1.1-41.5 9.3-23.1 16.4-27.9 35.8-28.9 52-0.4 7.1 1.1 15.8 3.7 23.2 2.1 6.1 9.3 18.6 9.6 16.9z" />
<!-- Анимация вращения планеты -->
<circle cx="0" cy="0" r="14" fill="url(#gradEarth)" >
<animateMotion begin="btn1.click" dur="4s" repeatCount="indefinite">
<mpath xlink:href="#orbita" />
</animateMotion>
</circle>
<!-- Дополнительная маскирующая зона солнца, чтобы не было видно вращения планеты с обратной строны солнца -->
<path id="sunR2" fill="#FF6600" d="m112.1 49.9c-6.3 4.8-8.2 7.1-11.6 11.3-5.5 6.6-10.3 12.7-14.7 19.6-5.5 8.7-10.2 18-14.5 27.4-3.2 7.2-5.7 14.6-8.3 22-2.2 6.2-6.3 14.3-6 18.9 0.4 5.8 6.9 7.4 11.4 9.6 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-7.2-34-19.8-44-7.7-6.2-25.6-8.6-29.1-6z" />
<!-- Включение видимости всей анимации -->
<rect width="100%" height="100%" fill="#321300" opacity="1" >
<set attributeName="opacity" begin="btn1.click" to="0" />
</rect>
<!-- Кнопка -->
<g id="btn1" onclick='play()' transform="translate(0 0)" >
<circle cx="180" cy="185" r="8" fill="url(#gradEarth)" />
<text id="txt1" x="150" y="170" font-size="1.2rem" fill="gold" >Start</text>
</g>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 10 200 200" >
<defs>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="2" />
</filter>
<!-- Эффект колыхания огня для протуберанцев солнца -->
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0005" numOctaves="5" result="turbulence" >
<animate attributeName="baseFrequency" dur="32s" values="0.0005;0.02;0.0005;0.02;0.0005" begin="btn1.click" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
<!-- Анимация градиента языков пламени -->
<radialGradient id="gradSun">
<stop offset="10%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;40%;10%;80%" begin="btn1.click" dur="2s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;#FF6200;gold" begin="btn1.click" dur="2s" repeatCount="indefinite" />
</stop>
</radialGradient>
<!-- Градиент окраски вращающейся планеты -->
<linearGradient id="gradEarth">
<stop offset="0%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- Фон -->
<rect width="100%" height="100%" fill="#321300" />
<!-- Протуберанцы солнца 1-ая группа -->
<path id="flame" class="flame" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" >
</path>
<!-- Орбита вращения планеты -->
<path id="orbita" transform="translate(-1,0)" d="m77.6 69.4c3.3-5.1 7.3-9.8 11.4-14.4 4.5-5.1 9.2-10.2 14.4-14.7 3.8-3.3 7.9-6.5 12.3-9 3.9-2.2 7.9-4.4 12.3-5.1 4.6-0.7 9.8-1 13.8 1.2 4.4 2.4 7.3 7.3 9 12 2.1 5.6 1.8 12 1.2 18-0.3 2.8-1.1 5.5-2.1 8.1-7.8 21.2-17.1 42.2-29.4 61.1-9.3 14.3-20.1 27.8-33 39-2.9 2.6-6.3 4.7-9.9 6.3-3.5 1.5-7.3 2.9-11.1 3-3.7 0.1-7.8 0-10.8-2.1-4.2-2.9-6.8-8-8.1-12.9-2-7.3-0.6-15.3 0.6-22.8 1.4-8.7 4.2-17.3 7.5-25.5 5.9-14.7 13.3-28.9 21.9-42.2z" style="fill:none;stroke:grey; stroke-width:2"/>
<!-- Правая половинка солнца -->
<path id="sunR" fill="#FF6600" d="m106.4 38.5c-6.3 4.8-12.1 10.7-15.5 14.9-5.5 6.6-11.7 13.6-16.5 21.1-6.1 9.6-10.8 20-15.4 30.4-3.3 7.4-6.5 14.8-8.6 22.6-1.3 4.6-2.7 9.5-2.4 14.1 0.4 5.8 12.4 13.2 20.4 17.1 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-8.6-32.4-19.8-44-9-9.3-31.3-20-34.8-17.4z" />
<!-- Левая половинка солнца -->
<path id="sunL" fill="#FF6600" d="m45.8 140.1c1.6-8.4 1.9-10.1 3.3-15.1 1.5-5.4 3.2-10.8 5.2-16 2.6-6.7 5.8-13.1 9.1-19.5 3.1-5.9 6.6-11.7 10.3-17.2 3.6-5.4 7.3-10.8 11.5-15.7 5.4-6.3 12.6-13.1 17.5-17.8 4.2-4.1-29.9 1.1-41.5 9.3-23.1 16.4-27.9 35.8-28.9 52-0.4 7.1 1.1 15.8 3.7 23.2 2.1 6.1 9.3 18.6 9.6 16.9z" />
<!-- Анимация вращения планеты -->
<circle cx="0" cy="0" r="12" fill="url(#gradEarth)" >
<animateMotion begin="btn1.click" dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbita" />
</animateMotion>
<!-- Анимация вращения планеты вокруг своей оси -->
<animateTransform attributeName="transform" type="rotate" dur="1.5s" values="0 0 0;360 0 0 " repeatCount="indefinite" />
</circle>
<!-- Дополнительная маскирующая зона солнца, чтобы не было видно вращения планеты с обратной строны солнца -->
<path id="sunR2" fill="#FF6600" d="m112.1 49.9c-6.3 4.8-8.2 7.1-11.6 11.3-5.5 6.6-10.3 12.7-14.7 19.6-5.5 8.7-10.2 18-14.5 27.4-3.2 7.2-5.7 14.6-8.3 22-2.2 6.2-6.3 14.3-6 18.9 0.4 5.8 6.9 7.4 11.4 9.6 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-7.2-34-19.8-44-7.7-6.2-25.6-8.6-29.1-6z" />
<!-- Включение видимости всей анимации -->
<rect width="100%" height="100%" fill="#321300" opacity="1" >
<set attributeName="opacity" begin="btn1.click" to="0" />
</rect>
<!-- Кнопка -->
<g id="btn1" >
<circle cx="180" cy="185" r="8" fill="url(#gradEarth)" />
<text id="txt1" x="150" y="170" font-size="1.2rem" fill="gold" >Start</text>
</g>
</svg>
Вариант #3
Всё тоже самое, как во втором варианте. Добавляется второй паттерн языков пламени. Два паттерна вращаются в разные стороны.
.flame {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun 40s linear infinite;
}
@keyframes rotate-sun {
0% {transform: rotateX(0deg)}
100% {transform: rotateZ(360deg);}
}
.flame2 {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun2 28s linear infinite;
}
@keyframes rotate-sun2 {
0% {transform: rotateX(360deg)}
100% {transform: rotateZ(0deg);}
}
Ниже полный код:
.flame {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun 40s linear infinite;
}
@keyframes rotate-sun {
0% {transform: rotateX(0deg)}
100% {transform: rotateZ(360deg);}
}
.flame2 {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun2 28s linear infinite;
}
@keyframes rotate-sun2 {
0% {transform: rotateX(360deg)}
100% {transform: rotateZ(0deg);}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 10 200 200" >
<defs>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="2" />
</filter>
<!-- Эффект колыхания огня для протуберанцов солнца -->
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="5" result="turbulence" >
<animate attributeName="baseFrequency" dur="32s" values="0.0005;0.02;0.0005;0.02;0.0005" begin="btn1.click" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
<!-- Анимация градиента языков пламени -->
<radialGradient id="gradSun">
<stop offset="20%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;40%;10%;80%" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;#FF6200;gold" begin="btn1.click" dur="3s" repeatCount="indefinite" />
</stop>
</radialGradient>
<!-- Градиент окраски вращающейся планеты -->
<linearGradient id="gradEarth">
<stop offset="0%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- Фон -->
<rect width="100%" height="100%" fill="#321300" />
<!-- Протуберанцы солнца -->
<path id="flame" class="flame" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" >
<!-- Анимация роста, уменьшения Протуберанцев солнца -->
<animateTransform
attributeName="transform"
type="scale"
begin="btn1.click"
dur="6s"
values="0.6;0.7;0.7;0.7;0.5;1"
repeatCount="indefinite" />
</path>
<!-- Протуберанцы солнца 2-ая группа -->
<path id="flame2" class="flame2" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" />
<!-- Орбита вращения планеты -->
<path id="orbita" transform="translate(-1,0)" d="m77.6 69.4c3.3-5.1 7.3-9.8 11.4-14.4 4.5-5.1 9.2-10.2 14.4-14.7 3.8-3.3 7.9-6.5 12.3-9 3.9-2.2 7.9-4.4 12.3-5.1 4.6-0.7 9.8-1 13.8 1.2 4.4 2.4 7.3 7.3 9 12 2.1 5.6 1.8 12 1.2 18-0.3 2.8-1.1 5.5-2.1 8.1-7.8 21.2-17.1 42.2-29.4 61.1-9.3 14.3-20.1 27.8-33 39-2.9 2.6-6.3 4.7-9.9 6.3-3.5 1.5-7.3 2.9-11.1 3-3.7 0.1-7.8 0-10.8-2.1-4.2-2.9-6.8-8-8.1-12.9-2-7.3-0.6-15.3 0.6-22.8 1.4-8.7 4.2-17.3 7.5-25.5 5.9-14.7 13.3-28.9 21.9-42.2z" style="fill:none;stroke:grey; stroke-width:2"/>
<!-- Правая половинка солнца -->
<path id="sunR" fill="#FF6600" d="m106.4 38.5c-6.3 4.8-12.1 10.7-15.5 14.9-5.5 6.6-11.7 13.6-16.5 21.1-6.1 9.6-10.8 20-15.4 30.4-3.3 7.4-6.5 14.8-8.6 22.6-1.3 4.6-2.7 9.5-2.4 14.1 0.4 5.8 12.4 13.2 20.4 17.1 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-8.6-32.4-19.8-44-9-9.3-31.3-20-34.8-17.4z" />
<!-- Левая половинка солнца -->
<path id="sunL" fill="#FF6600" d="m45.8 140.1c1.6-8.4 1.9-10.1 3.3-15.1 1.5-5.4 3.2-10.8 5.2-16 2.6-6.7 5.8-13.1 9.1-19.5 3.1-5.9 6.6-11.7 10.3-17.2 3.6-5.4 7.3-10.8 11.5-15.7 5.4-6.3 12.6-13.1 17.5-17.8 4.2-4.1-29.9 1.1-41.5 9.3-23.1 16.4-27.9 35.8-28.9 52-0.4 7.1 1.1 15.8 3.7 23.2 2.1 6.1 9.3 18.6 9.6 16.9z" />
<!-- Анимация вращения планеты -->
<circle cx="0" cy="0" r="12" fill="url(#gradEarth)" >
<animateMotion begin="btn1.click" dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbita" />
</animateMotion>
<!-- Анимация вращения планеты вокруг своей оси -->
<animateTransform attributeName="transform" type="rotate" dur="1.5s" values="0 0 0;360 0 0 " repeatCount="indefinite" />
</circle>
<!-- Дополнительная маскирующая зона солнца, чтобы не было видно вращения планеты с обратной строны солнца -->
<path id="sunR2" fill="#FF6600" d="m112.1 49.9c-6.3 4.8-8.2 7.1-11.6 11.3-5.5 6.6-10.3 12.7-14.7 19.6-5.5 8.7-10.2 18-14.5 27.4-3.2 7.2-5.7 14.6-8.3 22-2.2 6.2-6.3 14.3-6 18.9 0.4 5.8 6.9 7.4 11.4 9.6 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-7.2-34-19.8-44-7.7-6.2-25.6-8.6-29.1-6z" />
<!-- Включение видимости всей анимации -->
<rect width="100%" height="100%" fill="#321300" opacity="1" >
<set attributeName="opacity" begin="btn1.click" to="0" />
</rect>
<!-- Кнопка запуска анимации -->
<g id="btn1">
<circle cx="180" cy="185" r="8" fill="url(#gradEarth)" />
<text id="txt1" x="150" y="170" font-size="1.2rem" fill="gold" >Start</text>
</g>
</svg>
UPDATE
Добавлен вариант по комментарию:
А эту всю анимацию можно сделать, чтобы не по click работала, а постоянно работала без click?
.flame {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun 40s linear infinite;
}
@keyframes rotate-sun {
0% {transform: rotateX(0deg)}
100% {transform: rotateZ(360deg);}
}
.flame2 {
transform-origin: center;
transform-box:fill-box;
animation: rotate-sun2 28s linear infinite;
}
@keyframes rotate-sun2 {
0% {transform: rotateX(360deg)}
100% {transform: rotateZ(0deg);}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 10 200 200" >
<defs>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="2" />
</filter>
<!-- Эффект колыхания огня для протуберанцов солнца -->
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="5" result="turbulence" >
<animate attributeName="baseFrequency" dur="32s" values="0.0005;0.02;0.0005;0.02;0.0005" begin="0s" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="15" in="SourceGraphic" in2="turbulence" />
</filter>
<!-- Анимация градиента языков пламени -->
<radialGradient id="gradSun">
<stop offset="20%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;40%;10%;80%" begin="0s" dur="3s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;#FF6200;gold" begin="0s" dur="3s" repeatCount="indefinite" />
</stop>
</radialGradient>
<!-- Градиент окраски вращающейся планеты -->
<linearGradient id="gradEarth">
<stop offset="0%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- Фон -->
<rect width="100%" height="100%" fill="#321300" />
<!-- Протуберанцы солнца -->
<path id="flame" class="flame" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" >
<!-- Анимация роста, уменьшения Протуберанцев солнца -->
<animateTransform
attributeName="transform"
type="scale"
begin="0s"
dur="6s"
values="0.6;0.7;0.7;0.7;0.5;1"
repeatCount="indefinite" />
</path>
<!-- Протуберанцы солнца 2-ая группа -->
<path id="flame2" class="flame2" fill="url(#gradSun)" filter="url(#myFilter)" d="m181.9 82.8c-27.3 31.7 13 43-4.1 40.5-9.2-1.4-38.7 12.5-18 26.4 20.5 13.7-30-2.1-20.1 12.9 14.2 21.5-18.3-8.9-23 9.3-7.4 28.2-10.9 1.8-16.6 1.8-6.6 0-13.6 13.2-19.2-2.4-3.8-10.7-27.1-14.7-33.7 3.2-3.2 8.6-10.1-48-13.3-39.3C19.4 174.7 36.3 104.4 26.1 108.6 0.8 119.1 33.6 83.8 32.5 75.7 30.3 59.4 20.1 39.8 24.6 45.2 32.4 54.4 52.8 48.8 48.8 43.5 36.6 27.5 38.2 21 36.2 18.9 19.8 1.4 76 39.7 74.2 33.7 71.5 25.1 68.3 8.7 70.3 10.1c7.1 5 29.8 25.4 29.8 16.1-0.2-35.1 10.9 0.6 16.1 1.7 8.2 1.7 9.6 7.6 16.2 2.9 10.4-7.5 31.5-13.2 34.2-11.6 2.2 1.4-13.1 9.2-13.8 13.4-1.4 9.3-6.8 21.8-4.3 20.2 12.6-8.4 27.5-32.3 19.2-9.2-0.4 1.1-0.9 8.2-2.6 11.1-4.2 7.1-12.2 12.6-10.4 12.5 38.9-2.1 39.2-13.5 13.9 15.6-4.8 5.5 18.2-5.8 13.2 0z" />
<!-- Орбита вращения планеты -->
<path id="orbita" transform="translate(-1,0)" d="m77.6 69.4c3.3-5.1 7.3-9.8 11.4-14.4 4.5-5.1 9.2-10.2 14.4-14.7 3.8-3.3 7.9-6.5 12.3-9 3.9-2.2 7.9-4.4 12.3-5.1 4.6-0.7 9.8-1 13.8 1.2 4.4 2.4 7.3 7.3 9 12 2.1 5.6 1.8 12 1.2 18-0.3 2.8-1.1 5.5-2.1 8.1-7.8 21.2-17.1 42.2-29.4 61.1-9.3 14.3-20.1 27.8-33 39-2.9 2.6-6.3 4.7-9.9 6.3-3.5 1.5-7.3 2.9-11.1 3-3.7 0.1-7.8 0-10.8-2.1-4.2-2.9-6.8-8-8.1-12.9-2-7.3-0.6-15.3 0.6-22.8 1.4-8.7 4.2-17.3 7.5-25.5 5.9-14.7 13.3-28.9 21.9-42.2z" style="fill:none;stroke:grey; stroke-width:2"/>
<!-- Правая половинка солнца -->
<path id="sunR" fill="#FF6600" d="m106.4 38.5c-6.3 4.8-12.1 10.7-15.5 14.9-5.5 6.6-11.7 13.6-16.5 21.1-6.1 9.6-10.8 20-15.4 30.4-3.3 7.4-6.5 14.8-8.6 22.6-1.3 4.6-2.7 9.5-2.4 14.1 0.4 5.8 12.4 13.2 20.4 17.1 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-8.6-32.4-19.8-44-9-9.3-31.3-20-34.8-17.4z" />
<!-- Левая половинка солнца -->
<path id="sunL" fill="#FF6600" d="m45.8 140.1c1.6-8.4 1.9-10.1 3.3-15.1 1.5-5.4 3.2-10.8 5.2-16 2.6-6.7 5.8-13.1 9.1-19.5 3.1-5.9 6.6-11.7 10.3-17.2 3.6-5.4 7.3-10.8 11.5-15.7 5.4-6.3 12.6-13.1 17.5-17.8 4.2-4.1-29.9 1.1-41.5 9.3-23.1 16.4-27.9 35.8-28.9 52-0.4 7.1 1.1 15.8 3.7 23.2 2.1 6.1 9.3 18.6 9.6 16.9z" />
<!-- Анимация вращения планеты -->
<circle cx="0" cy="0" r="12" fill="url(#gradEarth)" >
<animateMotion begin="0s" dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbita" />
</animateMotion>
<!-- Анимация вращения планеты вокруг своей оси -->
<animateTransform attributeName="transform" type="rotate" dur="1.5s" values="0 0 0;360 0 0 " repeatCount="indefinite" />
</circle>
<!-- Дополнительная маскирующая зона солнца, чтобы не было видно вращения планеты с обратной строны солнца -->
<path id="sunR2" fill="#FF6600" d="m112.1 49.9c-6.3 4.8-8.2 7.1-11.6 11.3-5.5 6.6-10.3 12.7-14.7 19.6-5.5 8.7-10.2 18-14.5 27.4-3.2 7.2-5.7 14.6-8.3 22-2.2 6.2-6.3 14.3-6 18.9 0.4 5.8 6.9 7.4 11.4 9.6 9.7 4.8 21 8.1 31.8 6.9 16.7-1.9 34.3-9.1 45.5-21.6 10.4-11.6 16-28.5 15.3-44-0.7-16.1-7.2-34-19.8-44-7.7-6.2-25.6-8.6-29.1-6z" />
</svg>
Вот сообразил Вам солнышко, пока без планет
let rays = (n,s) => [...Array(n)].map((_, i) =>
`0 0 0 ${(i+s)*8}px #fd0${(i+s)===n?0:4}`
).join(',\n');
document.body.innerHTML += `
<style>
@keyframes rays {
0% {box-shadow:${rays(4,0)}}
100% {box-shadow:${rays(4,1)}}
}
</style>`;
body {
background-color: #000;
}
sun {
margin: 50px;
display: block;
width: 77px;
height: 77px;
background-color: #FFDE00;
border-radius: 50%;
animation: pulse 5s infinite, rays 2s infinite linear;
}
@keyframes pulse {
0% {transform: scale(1)}
20% {transform: scale(1.03,0.97)}
80% {transform: scale(0.97,1.03)}
100% {transform: scale(1)}
}
<sun></sun>
Добавил в ответ от soledar10 немного "косметики":
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #010101;
min-height: 100vh;
}
.system {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(80deg) rotateY(-20deg);
}
.sun,
.orbit,
.planet {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
border-radius: 50%;
}
.sun,
.planet {
width: 2em;
height: 2em;
margin-top: -1em;
margin-left: -1em;
}
.sun {
font-size: 6em;
background: radial-gradient(7em 1.2em, #944c05 1%, #b3a250 100%);
background-size: cover;
transform: rotateX(-90deg);
animation: animSun 8s linear infinite;
}
.orbit {
width: 24em;
height: 24em;
margin-top: -12em;
margin-left: -12em;
border: 2px dotted rgba(100, 100, 100, .8);
animation: animOrbit 12s linear infinite;
}
.planet {
background-color: #af8d27;
left: 100%;
animation: animPlanet 12s linear infinite;
}
@keyframes animSun {
0%, 100% { box-shadow: 0px 0px 25px -5px #Fa0, -4px -2px 15px -5px #FFEB3B, inset 0px 2px 15px -5px #FF5722; }
25% { box-shadow: 0px 0px 0px -5px #Fa0, 4px -2px 15px -5px #FFC107, inset -1px 0px 15px -5px #FFEB3B; }
50% { box-shadow: 0px 0px 25px -5px #Fa0, 2px 4px 15px -5px #FF5722, inset 0px -2px 15px -5px #FF9800; }
75% { box-shadow: 0px 0px 0px -5px #Fa0, -2px 4px 15px -5px #FFEB3B, inset 2px 0px 15px -5px #FFC107; }
}
@keyframes animOrbit {
0% { transform: rotateZ(180deg); }
100% { transform: rotateZ(-180deg); }
}
@keyframes animPlanet {
0% {
transform: rotateX(-90deg) rotateY(360deg) rotateZ(0deg) scale(1.5);
box-shadow: -6px 0px 18px -5px #Fa0, inset -27px 0 14px 5px black;
}
25% {
transform: rotateX(-90deg) rotateY(270deg) rotateZ(0deg) scale(2.0);
box-shadow: -6px 0px 18px -5px #Fa0, inset 0px 0 2px 27px black;
}
50% {
transform: rotateX(-90deg) rotateY(180deg) rotateZ(0deg) scale(1.5);
box-shadow: 6px 0px 18px -5px #Fa0, inset 27px 0 14px 5px black;
}
75% {
transform: rotateX(-90deg) rotateY(90deg) rotateZ(0deg) scale(.75);
box-shadow: 6px 0px 18px -5px #Fa0, inset 0px 0 1px 2px black;
}
100% {
transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg) scale(1.5);
box-shadow: -6px 0px 18px -5px #Fa0, inset -27px 0 14px 5px black;
}
}
<div class="system">
<div class="sun"></div>
<div class="orbit">
<div class="planet"></div>
</div>
</div>
Вот такая сценка на three.js:
let base64prefix = 'data:image/png;base64,'
let blue = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkuPn/PwAFkgLZdUNuXwAAAABJRU5ErkJggg=='
let blue2= 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkqPz/HwAEcgJ5UUczUQAAAABJRU5ErkJggg=='
let orange = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8H8PwHwAGGQJcoBRfLQAAAABJRU5ErkJggg=='
let solarsystem = [{
texture: blue,
name: 'earth', radius: 2, orbit: 30, speed: 2,
satellites: [{
texture: blue2, rotation: [1, 1, 1],
name: 'rock', radius: 0.5, orbit: 4, speed: 5,
},{
texture: blue2,
name: 'moon', radius: 1, orbit: 6, speed: 1,
}]
}, {
texture: orange,
name: 'mars', radius: 2, orbit: 50, speed: 1,
satellites: [{
texture: blue2,
name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
}, {
texture: blue2,
name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
}]
}];
var scene = new THREE.Scene();
var aspect = innerWidth / innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( innerWidth, innerHeight );
document.body.appendChild( renderer.domElement );
// planets
solarsystem.forEach(d => create(d, scene));
// sun
let sun = sphere({radius:3, orbit:0, texture: orange});
scene.add(sun)
scene.add(starfield())
function starfield() {
let vertices = [];
for ( let i = 0; i < 50000; i ++ ) {
let x = Math.random()*1000-500;
let y = Math.random()*1000-500;
let z = Math.random()*1000-500;
if (x*x+y*y+z*z > 1e5)
vertices.push( x, y, z );
}
let geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position',
new THREE.Float32BufferAttribute( vertices, 3 ) );
let material = new THREE.PointsMaterial( { color: 0xffffff } );
return new THREE.Points( geometry, material );
}
function create(d, target) {
var o = new THREE.Object3D(d.name);
d.rotation && o.rotateX(d.rotation[0]);
d.rotation && o.rotateY(d.rotation[1]);
d.rotation && o.rotateZ(d.rotation[2]);
o.add(orbit(d));
let p = sphere(d)
o.add(p);
d.satellites && d.satellites.forEach(d1 => create(d1, p))
target.add(o);
d.o=o;
}
function orbit(d) {
var o = new THREE.Object3D('orbit '+ d.name);
o.rotateX(Math.PI/2);
o.add( new THREE.Line(
new THREE.CircleGeometry( d.orbit, 64 ),
new THREE.LineBasicMaterial( { color: 0xffffff } ) ));
return o;
}
function sphere(d){
var o = new THREE.Object3D('sphere ' + d.name);
o.translateX(d.orbit);
var loader = new THREE.TextureLoader();
loader.load( base64prefix + d.texture, function ( texture ) {
var geometry = new THREE.SphereGeometry( d.radius, 20, 20 );
var material = new THREE.MeshBasicMaterial( {
map: texture
} );
o.add( new THREE.Mesh( geometry, material ) );
} );
return o;
}
camera.position.set(25,25,25);
new THREE.OrbitControls( camera, renderer.domElement );
let t = 0
function render(dt) {
let t2 = dt - t;
requestAnimationFrame( render );
renderer.render( scene, camera );
solarsystem.forEach(upd);
sun.rotateY(t2/1000);
t = dt;
function upd(d) {
d.o.rotateY(t2/10000*d.speed);
d.satellites && d.satellites.forEach(upd)
}
}
requestAnimationFrame( render );
addEventListener('resize', () => {
renderer.setSize( innerWidth, innerHeight );
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
})
body, canvas {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
