forked from tomshanley's block: Spiral heatmap
Built with blockbuilder.org
forked from tomshanley's block: Spiral heatmap (with mouseover)
license: mit | |
height: 900 |
forked from tomshanley's block: Spiral heatmap
Built with blockbuilder.org
forked from tomshanley's block: Spiral heatmap (with mouseover)
year | month | temperature | |
---|---|---|---|
1977 | 1 | 5.3 | |
1977 | 2 | 9 | |
1977 | 3 | 11 | |
1977 | 4 | 12.2 | |
1977 | 5 | 15.7 | |
1977 | 6 | 16.6 | |
1977 | 7 | 21.3 | |
1977 | 8 | 20 | |
1977 | 9 | 18.1 | |
1977 | 10 | 16.2 | |
1977 | 11 | 9.6 | |
1977 | 12 | 9 | |
1978 | 1 | 5.9 | |
1978 | 2 | 5.4 | |
1978 | 3 | 11.1 | |
1978 | 4 | 10.3 | |
1978 | 5 | 16 | |
1978 | 6 | 18.9 | |
1978 | 7 | 19.4 | |
1978 | 8 | 20.2 | |
1978 | 9 | 19.3 | |
1978 | 10 | 16.3 | |
1978 | 11 | 11.7 | |
1978 | 12 | 6.7 | |
1979 | 1 | 2.5 | |
1979 | 2 | 3.5 | |
1979 | 3 | 8.4 | |
1979 | 4 | 12.1 | |
1979 | 5 | 15.9 | |
1979 | 6 | 18.9 | |
1979 | 7 | 21.8 | |
1979 | 8 | 20.4 | |
1979 | 9 | 19.3 | |
1979 | 10 | 15.5 | |
1979 | 11 | 10 | |
1979 | 12 | 8.8 | |
1980 | 1 | 5.6 | |
1980 | 2 | 9.1 | |
1980 | 3 | 8.5 | |
1980 | 4 | 13.3 | |
1980 | 5 | 16.4 | |
1980 | 6 | 19.3 | |
1980 | 7 | 19.3 | |
1980 | 8 | 21.3 | |
1980 | 9 | 19.5 | |
1980 | 10 | 13.3 | |
1980 | 11 | 8.9 | |
1980 | 12 | 8.2 | |
1981 | 1 | 7.4 | |
1981 | 2 | 6.1 | |
1981 | 3 | 11 | |
1981 | 4 | 11.7 | |
1981 | 5 | 15.8 | |
1981 | 6 | 18.1 | |
1981 | 7 | 20.8 | |
1981 | 8 | 21.7 | |
1981 | 9 | 19.9 | |
1981 | 10 | 12.4 | |
1981 | 11 | 10.9 | |
1981 | 12 | 3 | |
1982 | 1 | 5.6 | |
1982 | 2 | 7.9 | |
1982 | 3 | 10.5 | |
1982 | 4 | 13.4 | |
1982 | 5 | 17.3 | |
1982 | 6 | 20.2 | |
1982 | 7 | 21.8 | |
1982 | 8 | 21.3 | |
1982 | 9 | 19.9 | |
1982 | 10 | 13.6 | |
1982 | 11 | 10.6 | |
1982 | 12 | 7.2 | |
1983 | 1 | 9.5 | |
1983 | 2 | 4.5 | |
1983 | 3 | 10.2 | |
1983 | 4 | 11.6 | |
1983 | 5 | 14.8 | |
1983 | 6 | 19.4 | |
1983 | 7 | 25.8 | |
1983 | 8 | 23.4 | |
1983 | 9 | 18.2 | |
1983 | 10 | 14.7 | |
1983 | 11 | 10.4 | |
1983 | 12 | 8.3 | |
1984 | 1 | 6.9 | |
1984 | 2 | 6.2 | |
1984 | 3 | 8 | |
1984 | 4 | 13.4 | |
1984 | 5 | 14 | |
1984 | 6 | 19.5 | |
1984 | 7 | 22.3 | |
1984 | 8 | 23.6 | |
1984 | 9 | 17.5 | |
1984 | 10 | 15.6 | |
1984 | 11 | 11.2 | |
1984 | 12 | 8.2 | |
1985 | 1 | 3.4 | |
1985 | 2 | 4.9 | |
1985 | 3 | 8.7 | |
1985 | 4 | 12.9 | |
1985 | 5 | 15.4 | |
1985 | 6 | 17.4 | |
1985 | 7 | 21.8 | |
1985 | 8 | 20.1 | |
1985 | 9 | 20.1 | |
1985 | 10 | 15.6 | |
1985 | 11 | 7.1 | |
1985 | 12 | 9.2 | |
1986 | 1 | 6.3 | |
1986 | 2 | 0.8 | |
1986 | 3 | 9.3 | |
1986 | 4 | 9.8 | |
1986 | 5 | 16.3 | |
1986 | 6 | 20.7 | |
1986 | 7 | 21.7 | |
1986 | 8 | 19.1 | |
1986 | 9 | 17.1 | |
1986 | 10 | 15.6 | |
1986 | 11 | 11 | |
1986 | 12 | 9 | |
1987 | 1 | 2.8 | |
1987 | 2 | 7.0 | |
1987 | 3 | 7.7 | |
1987 | 4 | 15.2 | |
1987 | 5 | 14.9 | |
1987 | 6 | 17.5 | |
1987 | 7 | 20.6 | |
1987 | 8 | 20.5 | |
1987 | 9 | 18.8 | |
1987 | 10 | 14.1 | |
1987 | 11 | 9 | |
1987 | 12 | 8.2 | |
1988 | 1 | 8 | |
1988 | 2 | 7.9 | |
1988 | 3 | 9.7 | |
1988 | 4 | 12.5 | |
1988 | 5 | 17 | |
1988 | 6 | 18.3 | |
1988 | 7 | 19.4 | |
1988 | 8 | 21.4 | |
1988 | 9 | 18.2 | |
1988 | 10 | 14.6 | |
1988 | 11 | 9.0 | |
1988 | 12 | 9.6 | |
1989 | 1 | 8.9 | |
1989 | 2 | 9.6 | |
1989 | 3 | 12.3 | |
1989 | 4 | 10.6 | |
1989 | 5 | 19.7 | |
1989 | 6 | 21.2 | |
1989 | 7 | 24.8 | |
1989 | 8 | 24.1 | |
1989 | 9 | 20.5 | |
1989 | 10 | 16.5 | |
1989 | 11 | 9.9 | |
1989 | 12 | 8.3 | |
1990 | 1 | 9.8 | |
1990 | 2 | 11.4 | |
1990 | 3 | 12.9 | |
1990 | 4 | 13.5 | |
1990 | 5 | 19.1 | |
1990 | 6 | 19.2 | |
1990 | 7 | 23.7 | |
1990 | 8 | 25.7 | |
1990 | 9 | 18.6 | |
1990 | 10 | 16.2 | |
1990 | 11 | 9.8 | |
1990 | 12 | 6.9 | |
1991 | 1 | 6.2 | |
1991 | 2 | 4.6 | |
1991 | 3 | 12 | |
1991 | 4 | 12.4 | |
1991 | 5 | 14.7 | |
1991 | 6 | 16.7 | |
1991 | 7 | 22.9 | |
1991 | 8 | 23.7 | |
1991 | 9 | 20.5 | |
1991 | 10 | 14.1 | |
1991 | 11 | 9.8 | |
1991 | 12 | 7.3 | |
1992 | 1 | 6.4 | |
1992 | 2 | 9.2 | |
1992 | 3 | 11.1 | |
1992 | 4 | 13.2 | |
1992 | 5 | 19.8 | |
1992 | 6 | 21.7 | |
1992 | 7 | 21.8 | |
1992 | 8 | 21.2 | |
1992 | 9 | 18.4 | |
1992 | 10 | 11.5 | |
1992 | 11 | 10.8 | |
1992 | 12 | 6.4 | |
1993 | 1 | 9.6 | |
1993 | 2 | 6.6 | |
1993 | 3 | 10.7 | |
1993 | 4 | 13.4 | |
1993 | 5 | 17.2 | |
1993 | 6 | 20.4 | |
1993 | 7 | 20.5 | |
1993 | 8 | 20.5 | |
1993 | 9 | 16.7 | |
1993 | 10 | 12.1 | |
1993 | 11 | 7.9 | |
1993 | 12 | 8.5 | |
1994 | 1 | 8.5 | |
1994 | 2 | 6.7 | |
1994 | 3 | 11.7 | |
1994 | 4 | 12.4 | |
1994 | 5 | 15.1 | |
1994 | 6 | 20.3 | |
1994 | 7 | 25.8 | |
1994 | 8 | 22.1 | |
1994 | 9 | 16.6 | |
1994 | 10 | 13.9 | |
1994 | 11 | 12.6 | |
1994 | 12 | 9.8 | |
1995 | 1 | 7.9 | |
1995 | 2 | 9.6 | |
1995 | 3 | 9.9 | |
1995 | 4 | 13.9 | |
1995 | 5 | 17.9 | |
1995 | 6 | 18.7 | |
1995 | 7 | 25.8 | |
1995 | 8 | 25.7 | |
1995 | 9 | 18 | |
1995 | 10 | 17.6 | |
1995 | 11 | 10.9 | |
1995 | 12 | 4.3 | |
1996 | 1 | 5.8 | |
1996 | 2 | 5.4 | |
1996 | 3 | 7.2 | |
1996 | 4 | 13.7 | |
1996 | 5 | 13.9 | |
1996 | 6 | 21.5 | |
1996 | 7 | 23.2 | |
1996 | 8 | 22.6 | |
1996 | 9 | 18.4 | |
1996 | 10 | 15.9 | |
1996 | 11 | 9.3 | |
1996 | 12 | 5.1 | |
1997 | 1 | 4.7 | |
1997 | 2 | 10.5 | |
1997 | 3 | 13 | |
1997 | 4 | 13.9 | |
1997 | 5 | 17.6 | |
1997 | 6 | 18.9 | |
1997 | 7 | 22.3 | |
1997 | 8 | 26.3 | |
1997 | 9 | 19.9 | |
1997 | 10 | 14.7 | |
1997 | 11 | 11.7 | |
1997 | 12 | 8.5 | |
1998 | 1 | 8.1 | |
1998 | 2 | 11.2 | |
1998 | 3 | 11.5 | |
1998 | 4 | 11.9 | |
1998 | 5 | 18.2 | |
1998 | 6 | 18.9 | |
1998 | 7 | 20.8 | |
1998 | 8 | 22.6 | |
1998 | 9 | 19.4 | |
1998 | 10 | 14 | |
1998 | 11 | 8.4 | |
1998 | 12 | 8.7 | |
1999 | 1 | 9.1 | |
1999 | 2 | 8.2 | |
1999 | 3 | 11.7 | |
1999 | 4 | 14.3 | |
1999 | 5 | 18.3 | |
1999 | 6 | 19.2 | |
1999 | 7 | 24.5 | |
1999 | 8 | 21.6 | |
1999 | 9 | 21.3 | |
1999 | 10 | 14.9 | |
1999 | 11 | 10.6 | |
1999 | 12 | 7.8 | |
2000 | 1 | 8.1 | |
2000 | 2 | 9.8 | |
2000 | 3 | 11.2 | |
2000 | 4 | 12.4 | |
2000 | 5 | 16.8 | |
2000 | 6 | 20.5 | |
2000 | 7 | 20.1 | |
2000 | 8 | 23.1 | |
2000 | 9 | 20 | |
2000 | 10 | 14 | |
2000 | 11 | 10.4 | |
2000 | 12 | 8.1 | |
2001 | 1 | 6.1 | |
2001 | 2 | 8.2 | |
2001 | 3 | 9 | |
2001 | 4 | 12.1 | |
2001 | 5 | 18.5 | |
2001 | 6 | 19.9 | |
2001 | 7 | 23.1 | |
2001 | 8 | 22.9 | |
2001 | 9 | 17.3 | |
2001 | 10 | 17.3 | |
2001 | 11 | 10.6 | |
2001 | 12 | 6.2 | |
2002 | 1 | 8.9 | |
2002 | 2 | 10.7 | |
2002 | 3 | 12 | |
2002 | 4 | 14.7 | |
2002 | 5 | 16.6 | |
2002 | 6 | 20.1 | |
2002 | 7 | 22 | |
2002 | 8 | 22.9 | |
2002 | 9 | 19.6 | |
2002 | 10 | 14.3 | |
2002 | 11 | 11.4 | |
2002 | 12 | 8.2 | |
2003 | 1 | 7 | |
2003 | 2 | 7.8 | |
2003 | 3 | 12.9 | |
2003 | 4 | 15.1 | |
2003 | 5 | 17.5 | |
2003 | 6 | 22.1 | |
2003 | 7 | 23.7 | |
2003 | 8 | 25.3 | |
2003 | 9 | 21.3 | |
2003 | 10 | 14 | |
2003 | 11 | 11.7 | |
2003 | 12 | 8.1 | |
2004 | 1 | 8.1 | |
2004 | 2 | 8.1 | |
2004 | 3 | 10.5 | |
2004 | 4 | 14.2 | |
2004 | 5 | 16.9 | |
2004 | 6 | 21.2 | |
2004 | 7 | 22 | |
2004 | 8 | 24 | |
2004 | 9 | 20.6 | |
2004 | 10 | 15 | |
2004 | 11 | 10.5 | |
2004 | 12 | 8.4 | |
2005 | 1 | 9.2 | |
2005 | 2 | 7.1 | |
2005 | 3 | 10.7 | |
2005 | 4 | 14.2 | |
2005 | 5 | 16.6 | |
2005 | 6 | 21.8 | |
2005 | 7 | 22 | |
2005 | 8 | 22.6 | |
2005 | 9 | 21.1 | |
2005 | 10 | 17.4 | |
2005 | 11 | 10.1 | |
2005 | 12 | 7.8 | |
2006 | 1 | 7 | |
2006 | 2 | 7 | |
2006 | 3 | 9 | |
2006 | 4 | 13.5 | |
2006 | 5 | 17.4 | |
2006 | 6 | 22.5 | |
2006 | 7 | 28.3 | |
2006 | 8 | 21.5 | |
2006 | 9 | 22.7 | |
2006 | 10 | 17.5 | |
2006 | 11 | 12.5 | |
2006 | 12 | 9.7 | |
2007 | 1 | 10.4 | |
2007 | 2 | 9.7 | |
2007 | 3 | 12.1 | |
2007 | 4 | 17.1 | |
2007 | 5 | 16.9 | |
2007 | 6 | 20.4 | |
2007 | 7 | 21.6 | |
2007 | 8 | 21.6 | |
2007 | 9 | 19.5 | |
2007 | 10 | 15.2 | |
2007 | 11 | 11.1 | |
2007 | 12 | 8.5 | |
2008 | 1 | 10.3 | |
2008 | 2 | 9.9 | |
2008 | 3 | 10.1 | |
2008 | 4 | 13.1 | |
2008 | 5 | 19 | |
2008 | 6 | 19.7 | |
2008 | 7 | 22.8 | |
2008 | 8 | 22.3 | |
2008 | 9 | 18.6 | |
2008 | 10 | 14.4 | |
2008 | 11 | 10.3 | |
2008 | 12 | 6.6 | |
2009 | 1 | 5.8 | |
2009 | 2 | 7.1 | |
2009 | 3 | 11.9 | |
2009 | 4 | 15.6 | |
2009 | 5 | 18.3 | |
2009 | 6 | 20.9 | |
2009 | 7 | 22.5 | |
2009 | 8 | 23.6 | |
2009 | 9 | 20.1 | |
2009 | 10 | 15.7 | |
2009 | 11 | 12 | |
2009 | 12 | 6.2 | |
2010 | 1 | 3.9 | |
2010 | 2 | 6.1 | |
2010 | 3 | 10.9 | |
2010 | 4 | 14.9 | |
2010 | 5 | 16.5 | |
2010 | 6 | 21.6 | |
2010 | 7 | 24.6 | |
2010 | 8 | 21 | |
2010 | 9 | 19 | |
2010 | 10 | 14.7 | |
2010 | 11 | 8.4 | |
2010 | 12 | 2.8 | |
2011 | 1 | 6.8 | |
2011 | 2 | 9.6 | |
2011 | 3 | 11.6 | |
2011 | 4 | 18.6 | |
2011 | 5 | 18.7 | |
2011 | 6 | 20.3 | |
2011 | 7 | 21.2 | |
2011 | 8 | 21.6 | |
2011 | 9 | 21.2 | |
2011 | 10 | 17.9 | |
2011 | 11 | 13.3 | |
2011 | 12 | 9.1 | |
2012 | 1 | 9.1 | |
2012 | 2 | 7 | |
2012 | 3 | 13.3 | |
2012 | 4 | 12.2 | |
2012 | 5 | 16.9 | |
2012 | 6 | 18.5 | |
2012 | 7 | 21.2 | |
2012 | 8 | 23.5 | |
2012 | 9 | 19.3 | |
2012 | 10 | 13.5 | |
2012 | 11 | 10 | |
2012 | 12 | 8.1 | |
2013 | 1 | 5.8 | |
2013 | 2 | 6 | |
2013 | 3 | 6.2 | |
2013 | 4 | 13.2 | |
2013 | 5 | 15.9 | |
2013 | 6 | 19.2 | |
2013 | 7 | 25.1 | |
2013 | 8 | 23.5 | |
2013 | 9 | 19 | |
2013 | 10 | 16.2 | |
2013 | 11 | 9.6 | |
2013 | 12 | 9.7 | |
2014 | 1 | 9.2 | |
2014 | 2 | 9.8 | |
2014 | 3 | 13.4 | |
2014 | 4 | 15.9 | |
2014 | 5 | 17.7 | |
2014 | 6 | 20.8 | |
2014 | 7 | 24.4 | |
2014 | 8 | 21 | |
2014 | 9 | 20.5 | |
2014 | 10 | 17 | |
2014 | 11 | 11.9 | |
2014 | 12 | 8.5 | |
2015 | 1 | 8 | |
2015 | 2 | 7.4 | |
2015 | 3 | 11.1 | |
2015 | 4 | 15 | |
2015 | 5 | 16.5 | |
2015 | 6 | 20.3 | |
2015 | 7 | 22.5 | |
2015 | 8 | 22.2 | |
2015 | 9 | 18.1 | |
2015 | 10 | 15.1 | |
2015 | 11 | 13.3 | |
2015 | 12 | 13.2 | |
2016 | 1 | 8.7 | |
2016 | 2 | 8.8 | |
2016 | 3 | 10 | |
2016 | 4 | 12.4 | |
2016 | 5 | 17.7 | |
2016 | 6 | 19.7 | |
2016 | 7 | 23.2 | |
2016 | 8 | 23.9 | |
2016 | 9 | 21.8 | |
2016 | 10 | 15 | |
2016 | 11 | 9.6 | |
2016 | 12 | 9.4 | |
2017 | 1 | 6.7 | |
2017 | 2 | 9.3 | |
2017 | 3 | 13.4 | |
2017 | 4 | 14.5 | |
2017 | 5 | 18.6 | |
2017 | 6 | 21.9 |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/d3-scale-chromatic.v0.3.min.js"></script> | |
<link href="https://fonts.googleapis.com/css?family=Catamaran" rel="stylesheet"> | |
<style> | |
body { | |
font-family: 'Catamaran', sans-serif; | |
margin: 20px; | |
top: 20px; | |
right: 20px; | |
bottom: 20px; | |
left: 20px; | |
} | |
line { | |
stroke: lightgray; | |
} | |
.arc text { | |
fill: white; | |
stroke: none; | |
pointer-events: none; | |
} | |
.text-path { | |
stroke: none; | |
fill: none; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Spiral heatmap</h1> | |
<p>An example of a spiral heatmap, showing monthly max temperature at Cambridge, UK from 1977 to 2017.</p> | |
<p>Data source: <a href="http://www.metoffice.gov.uk/pub/data/weather/uk/climate/stationdata/cambridgedata.txt">Metservice</a></p> | |
<div id="chart"></div> | |
<div id="legend"></div> | |
<script> | |
const radians = 0.0174532925; | |
//CHART CONSTANTS | |
const chartRadius = 300; | |
const chartWidth = chartRadius * 2; | |
const chartHeight = chartRadius * 2; | |
const labelRadius = chartRadius + 15; | |
const margin = { "top": 40, "bottom": 40, "left": 40, "right": 40 }; | |
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; | |
//CHART OPTIONS | |
const holeRadiusProportion = 0.1; //fraction of chartRadius. 0 gives you some pointy arcs in the centre. | |
const holeRadius = holeRadiusProportion * chartRadius; | |
const segmentsPerCoil = 12; //number of coils. for this example, I have 12 months per year. But you change to whatever suits your data. | |
const segmentAngle = 360 / segmentsPerCoil; | |
var coils; //number of coils, based on data.length / segmentsPerCoil | |
var coilWidth; //remaining chartRadius (after holeRadius removed), divided by coils + 1. I add 1 as the end of the coil moves out by 1 each time | |
//SCALES | |
var colour = d3.scaleSequential(d3.interpolatePlasma); | |
//CREATE SVG AND A G PLACED IN THE CENTRE OF THE SVG | |
const svg = d3.select("#chart") | |
.append("svg") | |
.attr("width", chartWidth + margin.left + margin.right) | |
.attr("height", chartHeight + margin.top + margin.bottom); | |
const g = svg.append("g") | |
.attr("transform", "translate(" | |
+ (margin.left + chartRadius) | |
+ "," | |
+ (margin.top + chartRadius) + ")"); | |
//LOAD THE DATA | |
d3.csv("cambridge_maxtemp.csv", convertTextToNumbers, function (error, data) { | |
if (error) { throw error; }; | |
//ENSURE THE DATA IS SORTED CORRECTLY, IN THIS CASE BY YEAR AND MONTH | |
//THE SPIRAL WILL START IN THE MIDDLE AND WORK OUTWARDS | |
data.sort(function (a, b) { | |
return a.year - b.year || a.month - b.month; | |
}); | |
//CALCULATE AND STORE THE REMAING | |
var dataLength = data.length; | |
coils = Math.ceil(dataLength / segmentsPerCoil); | |
coilWidth = (chartRadius * (1 - holeRadiusProportion)) / (coils + 1); | |
//console.log("coilWidth: " + coilWidth); | |
var dataExtent = d3.extent(data, function (d) { return d.temperature; }); | |
console.log(dataExtent); | |
colour.domain(dataExtent); | |
//ADD LABELS AND GRIDS FOR EACH MONTH FIRST | |
//SO THE GRID LINES APPEAR BEHIND THE SPIRAL | |
var monthLabels = g.selectAll(".month-label") | |
.data(months) | |
.enter() | |
.append("g") | |
.attr("class", "month-label"); | |
monthLabels.append("text") | |
.text(function (d) { return d; }) | |
.attr("x", function (d, i) { | |
let labelAngle = (i * segmentAngle) + (segmentAngle / 2); | |
return x(labelAngle, labelRadius); | |
}) | |
.attr("y", function (d, i) { | |
let labelAngle = (i * segmentAngle) + (segmentAngle / 2); | |
return y(labelAngle, labelRadius); | |
}) | |
.style("text-anchor", function (d, i) { | |
return i < (months.length / 2) ? "start" : "end"; | |
}); | |
monthLabels.append("line") | |
.attr("x2", function (d, i) { | |
let lineAngle = (i * segmentAngle); | |
let lineRadius = chartRadius + 50; | |
return x(lineAngle, lineRadius); | |
}) | |
.attr("y2", function (d, i) { | |
let lineAngle = (i * segmentAngle); | |
let lineRadius = chartRadius + 50; | |
return y(lineAngle, lineRadius); | |
}); | |
//ASSUMING DATA IS SORTED, CALCULATE EACH DATA POINT'S SEGMENT VERTICES AND CONTROL POINTS | |
data.forEach(function (d, i) { calculateArc(d, i); }); | |
var arcs = g.selectAll(".arc") | |
.data(data) | |
.enter() | |
.append("g") | |
.attr("class", "arc"); | |
//STRAIGHT EDGES | |
/* | |
arcs.append("path") | |
.attr("d", function (d) { | |
let M = "M " + d.x1 + " " + d.y1; | |
let L1 = "L " + d.x2 + " " + d.y2; | |
let L2 = "L " + d.x3 + " " + d.y3; | |
let L3 = "L " + d.x4 + " " + d.y4; | |
return M + " " + L1 + " " + L2 + " " + L3 + " Z" | |
}) | |
//.style("fill", function (d) { return colour(d.temperature); }) | |
.style("fill", "white") | |
.style("stroke", "white") | |
*/ | |
//CURVED EDGES | |
arcs.append("path") | |
.attr("class", "arc-segment") | |
.attr("d", function (d) { | |
//start at vertice 1 | |
let start = "M " + d.x1 + " " + d.y1; | |
//inner curve to vertice 2 | |
let side1 = " Q " + d.controlPoint1x + " " + d.controlPoint1y + " " + d.x2 + " " + d.y2; | |
//straight line to vertice 3 | |
let side2 = "L " + d.x3 + " " + d.y3; | |
//outer curve vertice 4 | |
let side3 = " Q " + d.controlPoint2x + " " + d.controlPoint2y + " " + d.x4 + " " + d.y4; | |
//combine into string, with closure (Z) to vertice 1 | |
return start + " " + side1 + " " + side2 + " " + side3 + " Z" | |
}) | |
.style("fill", function (d) { return colour(d.temperature); }) | |
/*.on("mouseover", function (d) { | |
//HIGHLIGHT ARCS FROM THE SAME MONTH, OR WITHIN A 6 MONTH PERIOD EITHER SIDE | |
let thisMonth = d.month; | |
let lowerLimit = d.index - 6; | |
let upperLimit = d.index + 6; | |
arcs.selectAll(".arc-segment") | |
.style("opacity", function (a) { | |
if (a.month == thisMonth) { | |
return 1; | |
} else if (a.index > lowerLimit && a.index < upperLimit) { | |
return 1; | |
} else { | |
return 0.1 | |
}; | |
}); | |
}) | |
.on("mouseout", function (d) { | |
arcs.selectAll(".arc-segment").style("opacity", 1); | |
});*/ | |
//ADD LABELS FOR THE YEAR AT THE START OF EACH COIL (IE THE FIRST MONTH) | |
/*var yearLabels = arcs.filter(function (d) { return d.month == 1; }).raise(); | |
yearLabels.append("path") | |
.attr("class", "text-path") | |
.attr("id", function (d) { return "path-" + d.year; }) | |
.attr("d", function (d) { | |
//start at vertice 1 | |
let start = "M " + d.x1 + " " + d.y1; | |
//inner curve to vertice 2 | |
let side1 = " Q " + d.controlPoint1x + " " + d.controlPoint1y + " " + d.x2 + " " + d.y2; | |
return start + side1; | |
}); | |
yearLabels.append("text") | |
.attr("class", "year-label") | |
.attr("x", 3) | |
.attr("dy", -5) | |
.append("textPath") | |
.attr("xlink:href", function (d) { | |
return "#path-" + d.year; | |
}) | |
.text(function (d) { return d.year; }) | |
*/ | |
//DRAW LEGEND | |
const legendWidth = chartRadius; | |
const legendHeight = 20; | |
const legendPadding = 40; | |
var legendSVG = d3.select("#legend") | |
.append("svg") | |
.attr("width", legendWidth + legendPadding + legendPadding) | |
.attr("height", legendHeight + legendPadding + legendPadding); | |
var defs = legendSVG.append("defs"); | |
var legendGradient = defs.append("linearGradient") | |
.attr("id", "linear-gradient") | |
.attr("x1", "0%") | |
.attr("y1", "0%") | |
.attr("x2", "100%") | |
.attr("y2", "0%"); | |
let noOfSamples = 20; | |
let dataRange = dataExtent[1] - dataExtent[0]; | |
let stepSize = dataRange / noOfSamples; | |
for (i = 0; i < noOfSamples; i++) { | |
legendGradient.append("stop") | |
.attr("offset", (i / (noOfSamples - 1))) | |
.attr("stop-color", colour(dataExtent[0] + (i * stepSize))); | |
} | |
var legendG = legendSVG.append("g") | |
.attr("class", "legendLinear") | |
.attr("transform", "translate(" + legendPadding + "," + legendPadding + ")"); | |
legendG.append("rect") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("width", legendWidth) | |
.attr("height", legendHeight) | |
.style("fill", "url(#linear-gradient)"); | |
legendG.append("text") | |
.text("Cooler (-0.1c)") | |
.attr("x", 0) | |
.attr("y", legendHeight - 35) | |
.style("font-size", "12px"); | |
legendG.append("text") | |
.text("Warmer (28.3c)") | |
.attr("x", legendWidth) | |
.attr("y", legendHeight - 35) | |
.style("text-anchor", "end") | |
.style("font-size", "12px"); | |
}); | |
//RETURNS THE X COORDINATE GIVEN A CERTAIN RADIUS AND ANGLE | |
function x(angle, radius) { | |
//change to clockwise | |
let a = 360 - angle; | |
//start from 12 o'clock | |
a = a + 180; | |
return radius * Math.sin(a * radians); | |
}; | |
//RETURNS THE Y COORDINATE GIVEN A CERTAIN RADIUS AND ANGLE | |
function y(angle, radius) { | |
//change to clockwise | |
let a = 360 - angle; | |
//start from 12 o'clock | |
a = a + 180; | |
return radius * Math.cos(a * radians); | |
}; | |
//CALCULATES THE VERTICES AND CONTROL POINTS FOR DRAWING EACH ARC'S PATH | |
function calculateArc(d, i) { | |
d.index = i; | |
let coil = Math.floor(i / segmentsPerCoil); | |
let position = i - (coil * segmentsPerCoil); | |
//console.log("positions: " + i + " " + coil + " " + position); | |
let startAngle = position * segmentAngle; | |
let endAngle = (position + 1) * segmentAngle; | |
//console.log("angles: " + startAngle + " " + endAngle); | |
//console.log(holeRadius + " " + segmentsPerCoil + " " + coilWidth) | |
let startInnerRadius = holeRadius + ((i / segmentsPerCoil) * coilWidth) | |
let startOuterRadius = holeRadius + ((i / segmentsPerCoil) * coilWidth) + coilWidth; | |
let endInnerRadius = holeRadius + (((i + 1) / segmentsPerCoil) * coilWidth) | |
let endOuterRadius = holeRadius + (((i + 1) / segmentsPerCoil) * coilWidth) + coilWidth; | |
//console.log("start radi: " + startInnerRadius + " " + startOuterRadius); | |
//console.log("end radi: " + endInnerRadius + " " + endOuterRadius); | |
//vertices of each segment | |
d.x1 = x(startAngle, startInnerRadius); | |
d.y1 = y(startAngle, startInnerRadius); | |
d.x2 = x(endAngle, endInnerRadius); | |
d.y2 = y(endAngle, endInnerRadius); | |
d.x3 = x(endAngle, endOuterRadius); | |
d.y3 = y(endAngle, endOuterRadius); | |
d.x4 = x(startAngle, startOuterRadius); | |
d.y4 = y(startAngle, startOuterRadius); | |
//CURVE CONTROL POINTS | |
let midAngle = startAngle + (segmentAngle / 2) | |
let midInnerRadius = holeRadius + (((i + 0.5) / segmentsPerCoil) * coilWidth) | |
let midOuterRadius = holeRadius + (((i + 0.5) / segmentsPerCoil) * coilWidth) + coilWidth; | |
//MID POINTS, WHERE THE CURVE WILL PASS THRU | |
d.mid1x = x(midAngle, midInnerRadius); | |
d.mid1y = y(midAngle, midInnerRadius); | |
d.mid2x = x(midAngle, midOuterRadius); | |
d.mid2y = y(midAngle, midOuterRadius); | |
//FROM https://stackoverflow.com/questions/5634460/quadratic-b%C3%A9zier-curve-calculate-points | |
d.controlPoint1x = (d.mid1x - (0.25 * d.x1) - (0.25 * d.x2)) / 0.5; | |
d.controlPoint1y = (d.mid1y - (0.25 * d.y1) - (0.25 * d.y2)) / 0.5; | |
d.controlPoint2x = (d.mid2x - (0.25 * d.x3) - (0.25 * d.x4)) / 0.5; | |
d.controlPoint2y = (d.mid2y - (0.25 * d.y3) - (0.25 * d.y4)) / 0.5; | |
//console.log(d); | |
}; | |
function convertTextToNumbers(d) { | |
d.year = +d.year; | |
d.month = +d.month; | |
d.temperature = +d.temperature; | |
return d; | |
}; | |
</script> | |
</body> |