|  | # This will make the QGIS use a world projection and then move the center | 
        
          |  | # of the CRS sequentially to create a spinning globe effect | 
        
          |  | import os | 
        
          |  | from PyQt5.QtGui import QImage, QPainter | 
        
          |  | from PyQt5.QtCore import QEasingCurve | 
        
          |  | os.system('rm /tmp/globe*') | 
        
          |  | # Make this a big number while testing e.g. 19 | 
        
          |  | # small number e.g. 1 will make for a smooth animation | 
        
          |  | longitude_increments = -1 | 
        
          |  | image_counter = 1 | 
        
          |  | # Keep the scales the same if you dont want it to zoom in an out | 
        
          |  | max_scale = 58589836 | 
        
          |  | min_scale = 1830932 | 
        
          |  |  | 
        
          |  | def render_image(name): | 
        
          |  | size = iface.mapCanvas().size() | 
        
          |  | image = QImage(size, QImage.Format_RGB32) | 
        
          |  |  | 
        
          |  | painter = QPainter(image) | 
        
          |  | settings = iface.mapCanvas().mapSettings() | 
        
          |  |  | 
        
          |  | # You can fine tune the settings here for different | 
        
          |  | # dpi, extent, antialiasing... | 
        
          |  | # Just make sure the size of the target image matches | 
        
          |  |  | 
        
          |  | job = QgsMapRendererCustomPainterJob(settings, painter) | 
        
          |  | job.renderSynchronously() | 
        
          |  | painter.end() | 
        
          |  | image.save(name) | 
        
          |  |  | 
        
          |  | # See https://doc.qt.io/qt-5/qeasingcurve.html#Type-enum | 
        
          |  | # For the full list of available easings | 
        
          |  | map_easing = QEasingCurve(QEasingCurve.InBounce) | 
        
          |  | zoom_easing = QEasingCurve(QEasingCurve.InQuad) | 
        
          |  |  | 
        
          |  | for i in range(360, 0, longitude_increments): | 
        
          |  | longitude = i - 180 | 
        
          |  | # Get latitude_factor as but scaled between 0 - 180 | 
        
          |  | latitude_factor = i / 2 | 
        
          |  | # Scale latitude_factor to a positive number from 0 to 1 for use in the easing function | 
        
          |  | # we invert the result so the flight starts at the equator rather than the poles | 
        
          |  | latitude_easing_factor = 1 - (latitude_factor / 180) | 
        
          |  | # Multiply j by the easing of y_value to create a nice wobbly effect | 
        
          |  | # as the earth rotates | 
        
          |  | latitude = (latitude_factor * map_easing.valueForProgress(latitude_easing_factor) - 90) | 
        
          |  | definition = ( | 
        
          |  | '+proj=ortho +lat_0=%f +lon_0=%f +x_0=0 +y_0=0 +ellps=sphere +units=m +no_defs' % (latitude, longitude)) | 
        
          |  | crs = QgsCoordinateReferenceSystem() | 
        
          |  | crs.createFromProj(definition) | 
        
          |  | iface.mapCanvas().setDestinationCrs(crs) | 
        
          |  |  | 
        
          |  | # Now use easings for zoom level too | 
        
          |  | zoom_easing_factor = zoom_easing.valueForProgress(latitude_easing_factor) | 
        
          |  | scale = ((max_scale - min_scale) * zoom_easing_factor) + min_scale | 
        
          |  | print('Longitude: %f Latitude: %f Latitude Easing Factor: %f Zoom Easing Factor %f Zoom Scale: %f' % | 
        
          |  | (longitude, latitude, latitude_easing_factor, zoom_easing_factor, scale)) | 
        
          |  | if zoom_easing_factor == 1: | 
        
          |  | iface.mapCanvas().zoomToFullExtent() | 
        
          |  | else: | 
        
          |  | iface.mapCanvas().zoomScale(scale) | 
        
          |  | name = ('/tmp/globe-%03d.png' % image_counter) | 
        
          |  | render_image(name) | 
        
          |  | image_counter += 1 | 
        
          |  |  | 
        
          |  | # Now generate the GIF. If this fails try run the call from the command line | 
        
          |  | # and check the path to convert (provided by ImageMagick) is correct... | 
        
          |  | # delay of 3.33 makes the output around 30fps | 
        
          |  | os.system('/usr/bin/convert -delay 3.33 -loop 0 /tmp/globe-*.png /tmp/globe.gif') | 
        
          |  | # Now do a second pass with image magick to resize and compress the gif as much as possible. | 
        
          |  | # The remap option basically takes the first image as a reference inmage for the colour palette | 
        
          |  | # Depending on you cartography you may also want to bump up the colors param to increase palette size | 
        
          |  | # and of course adjust the scale factor to the ultimate image size you want | 
        
          |  | os.system('/usr/bin/convert /tmp/globe.gif -coalesce -scale 600x600 -fuzz 2% +dither -remap /tmp/globe.gif[20] +dither -colors 14 -layers Optimize /tmp/globe_small.gif') | 
        
          |  | # Also we will make a video of the scene - useful for cases where you have a larger colour | 
        
          |  | # pallette and gif will not hack it | 
        
          |  | # Pad option is to deal with cases where ffmpeg complains because the h or w of the image | 
        
          |  | # is an odd number of pixels. | 
        
          |  | # :color=white pads the video with white pixels. Change to black if needed. | 
        
          |  | #os.system('ffmpeg -framerate 30 -pattern_type glob -i "/tmp/globe-*.png" -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2:color=white" -c:v libx264 -pix_fmt yuv420p /tmp/globe.mp4') | 
  
Now with label support since qgis/QGIS#46727