I try to make an animated graph like the one below (the value changes according to the post's lenght). I need about ten poles to be animated. I suppose that using drivers may be a good solution, but I don't know how to achieve it. Thanks in advance.
1 Answer
There are two techniques for animating text.
The first technique is to have a vast number of text objects whose hide_render property (the camera icon in the outliner) is keyframed so that each only shows up in the rendered scene for the appropriate frame or frames.
The other is to use a frame_change_pre handler (python) to change the body of the text curve.
Here is a modified version of the example from Garrett's answer to How can I make dynamic text in an animation?
import bpy
scene = bpy.context.scene
def recalculate_text(scene):
obj = bpy.data.objects['Text']
bar = bpy.data.objects['Cube']
obj.data.body = "h=%.1f" % bar.dimensions[2]
obj.location[2] = bar.dimensions[2] + bar.location[2] + 0.2
bpy.app.handlers.frame_change_pre.append(recalculate_text)
(I modified the default cube by moving its origin to the bottom of the cube, and animated its Z size property).
You would have to put this python script in a text buffer and run it. If you want it to automatically run every time blender loads the file you should give the text buffer a name ending in .py and click the Register checkbox for that text buffer. This also means you will have to load the .blend file Trusted (either using the Reload Trusted button, or by invoking blender with the -y flag).
The other technique of having a swarm of text curves whose visibility is animated is demonstrated at http://web.purplefrog.com/~thoth/blender/python-cookbook/data-graph.html . Here is a relevant excerpt:
def setVisibility(obj, f1, f2):
if not f2 is None:
obj.keyframe_insert(data_path='hide', frame= bpy.context.scene.frame_end+10)
obj.keyframe_insert(data_path='hide_render', frame=f1)
obj.keyframe_insert(data_path='hide', frame=f1)
obj.hide = True
obj.hide_render = True
obj.keyframe_insert(data_path='hide', frame=0)
obj.keyframe_insert(data_path='hide_render', frame=0)
if not f2 is None:
obj.keyframe_insert(data_path='hide', frame=f2)
obj.keyframe_insert(data_path='hide_render', frame=f2)
def makeText(text, loc, f1, f2):
curve = bpy.data.curves.new("label", 'FONT')
curve.body = text
o1 = bpy.data.objects.new("label", curve)
bpy.context.scene.objects.link(o1)
o1.location = loc
if not f1 is None:
setVisibility(o1, f1, f2)
o1.parent = bpy.data.objects["font folder"]
curve.materials.append(bpy.data.materials["text"])
return o1
def make2Text(text1, text2, loc, f1, f2):
o1 = makeText(text1, loc, f1, f2)
o2 = makeText(text2, loc, f1, f2)
o1.data.align = 'RIGHT'
return (o1, o2)
# animating text by creating hundreds of individual text objects that pop in and out
f1 = -1
for i,xy in enumerate(data):
f2 = frameForX(i, len(data), f0, f9)
f3 = frameForX(i+1, len(data), f0, f9)
if (i+1 >= len(data)):
f3 = None
if (f2>f1):
make2Text("x=%d,"%xy[0], "y=%.1f"%xy[1], [4,6,1], f2, f3)
f1 = f2
-
$\begingroup$ Thanks for the solutions @Mutant Bob! I'll check out all of them. $\endgroup$ Jun 22, 2015 at 17:19