A MetaPost solution. It happens that I have already devised such a macro for a course I'm currently teaching, which can be applied to any function curve. Here it is, slightly modified and applied to the parabola y = 4x-x^2. The slopes are computed by MetaPost itself and rounded to an arbitrary number of digits with the help of the numprint package. (Since the slopes are known here to have integer values, I've instructed numprint to round them to the nearest integer: \nprounddigits{0}, but it can be changed at will.)
The MetaPost coding has been inserted in a LuaLaTeX program for better convenience:
\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
\mplibsetformat{metafun}
\mplibtextextlabel{enable}
\mplibnumbersystem{double}
\usepackage{numprint}
\nprounddigits{0}
\begin{document}
\begin{mplibcode}
input mpcolornames;
% Parameters
numeric u, v, xmin, xmax, xstep, ymin, ymax;
u = v = 1cm; xmin = -2; xmax = 6; xstep = 0.1;
ymin = -6; ymax = 6;
% Graph definition
vardef f (expr x) = 4x - x**2 enddef;
path my_graph;
my_graph = function(2, "x", "f(x)", xmin, xmax, xstep);
% Macro creating triangle with slope
def triangle_with_slope(expr p, A) =
% Basis and height
h := 1; a := xpart A; b := a + h;
% Direction
pair vdir, B;
vdir = direction ((a-xmin)/xstep) of p;
B = A + vdir/xpart(vdir);
% tangent and triangle
path tangente, Delta_x, Delta_y, triangle;
Delta_x = (A -- (xpart B, ypart A)) xyscaled (u, v);
Delta_y = ((xpart B, ypart A) -- B) xyscaled (u, v);
tangente = (A -- B) xyscaled (u, v);
triangle = (A -- (xpart B, ypart A) -- B -- cycle) xyscaled (u, v);
% The drawing
drawoptions(withcolor DarkRed);
fill triangle withcolor Pink; draw tangente;
drawarrow Delta_x; drawarrow Delta_y;
drawdot A xyscaled (u, v) withpen pencircle scaled 3bp;
% Labels
string slope; slope := decimal(ypart(B-A));
labeloffset := 2bp;
label. if ypart(B-A)>0: bot else: top fi ("$1$", point .5 of Delta_x);
freelabel("$\numprint{" & slope & "}$", point .5 of Delta_y, center triangle);
drawoptions( );
enddef;
beginfig(1);
% Axes
drawarrow (xmin*u, 0) -- (xmax*u, 0);
drawarrow (0, ymin*v) -- (0, ymax*v);
% Graph and triangles with slope
for i = -1 upto 4: triangle_with_slope(my_graph, (i, f(i))); endfor
picture parabola; parabola = image(draw my_graph xyscaled (u, v));
clip parabola to
((xmin, ymin) -- (xmax, ymin) -- (xmax, ymax) -- (xmin, ymax) -- cycle)
xyscaled (u, v);
draw parabola;
% Marks
labeloffset := 5bp;
label.bot("$x$", (xmax*u, 0)); label.lft("$y$", (0, ymax*v));
for i = -2 upto 5: if i<>0: draw (i*u, -3bp) -- (i*u, 3bp); fi endfor
for j = -6 upto 5: if j<>0: draw (-3bp, j*v) -- (3bp, j*v); fi endfor
label.bot("$1$", (u, 0)); label.lft("$1$", (0, v));
endfig;
\end{mplibcode}
\end{document}
Output:
