思路

其实不用管什么时间,星期,直接按固定数量进行填充即刻,

  • 生成一个7 * 9 列的格子方阵,一共是63天
  • 定一个json,并将63天的文章数据填充进去
    • 如果最后一个篇文章是星期5,则可能会少2篇文章,此时填充2篇空文章进去
  • 在生成格子的时候将文章数据附加进html元素内。
  • 完成
<div class="grid-container" id="gridContainer"></div>
  .grid-container {
    display: grid;
    grid-template-columns: repeat(9, 20px); /* 9列,每列20px */
    grid-template-rows: repeat(7, 20px); /* 7行,每行20px */
    width: 200px;
    height: 200px;
    gap: 5px; /* 格子间的间隙 */
  }
  .grid-column {
    display: grid;
    gap: 5px;
  }
  .grid-item {
    border: 1px solid #ddd; /* 边框颜色 */
    display: flex;
    align-items: center;
    justify-content: center;
  }
  /* 根据字数给格子添加背景色 */
  .word-count {
    font-size: 10px;
  }

1.0版本

const articles = [
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},
    {word:1},    
];
 
// 将文章数据填充到格子中
function fillGrid(articles) {
  const gridContainer = document.getElementById('gridContainer');
  const gridItemTemplate = document.createElement('div');
  gridItemTemplate.className = 'grid-item';
 
  // 填充格子
  articles.forEach((article, index) => {
    // 复制模板格子
    const gridItem = gridItemTemplate.cloneNode(false);
    gridItem.innerHTML = `<div class="word-count">${article.word}</div>`;
 
    // 确定格子位置,这里我们假设每列代表10天
    const colIndex = Math.floor(index / 7); // 计算列索引
    const rowIndex = index % 7; // 计算行索引
 
    // 将格子插入到正确的位置
    gridContainer.append(gridItem);
  });
}
 
fillGrid(articles);

完整版

const data = [
    {date:'2024-05-17'},
    {date:'2024-05-01'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-03'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-05'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-05'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-25'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-3'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-04'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
        {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
        {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-30'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
        {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-06'},
    {date:'2024-05-17'},
    {date:'2024-05-17'},
    {date:'2024-05-02'},
    {date:'2024-05-17'},
];
 
// 将字符串日期转换为日期对象的函数
function parseDate(str) {
    return new Date(str);
}
 
// 获取今天是星期几(0-6,0代表星期天,1代表星期一,以此类推)
function getDayOfWeek(date) {
    return date.getDay();
}
 
// 找到最近的星期天的日期
function getSundayBeforeDate(date) {
    const dayOfWeek = getDayOfWeek(date);
    // 如果今天是星期天,直接返回今天
    if (dayOfWeek === 0) return date;
    // 否则,往前找最近的星期天
    return new Date(date.getTime() - dayOfWeek * 24 * 60 * 60 * 1000);
}
 
function getThisSunday(date) {
    // 获取今天是星期几,1是星期天,2是星期一,依此类推
    const dayOfWeek = date.getDay();
    
    // 如果今天是星期天,直接返回这个日期
    if (dayOfWeek === 0) {
        return date;
    }
    
    // 如果不是星期天,计算到这个星期天还需要多少天
    // 因为getDay()中0是星期天,所以我们需要减去当前的dayOfWeek
    const daysToSunday = 7 - dayOfWeek;
    
    // 创建一个新日期,代表这个星期天
    const thisSunday = new Date(date);
    thisSunday.setDate(thisSunday.getDate() + daysToSunday);
    
    return thisSunday;
}
 
// 今天的日期
const today = new Date('2024-05-17');
 
// 找到最近的星期天
const sunday = getThisSunday(today);
 
// 创建一个从最近的星期天往前推63天的日期对象
let startDate = new Date(sunday);
startDate.setDate(sunday.getDate() - 62);
 
// 初始化结果数组
const result = [];
 
// 转换所有日期并统计每个日期出现的次数
const dateCounts = {};
data.forEach(item => {
    const dateObj = parseDate(item.date);
    const dateStr = dateObj.toISOString().split('T')[0];
    dateCounts[dateStr] = (dateCounts[dateStr] || 0) + 1;
});
 
// 填充结果数组
for (let currentDate = sunday; currentDate >= startDate; currentDate.setDate(currentDate.getDate() - 1)) {
    // 格式化日期为字符串
    const dateStr = currentDate.toISOString().split('T')[0];
    // 计算今天的日期在原始数据中出现的次数
    const count = dateCounts[dateStr] || 0;
    // 找到所有匹配当前日期的对象
    const dataContent = data.filter(item => parseDate(item.date).toISOString().split('T')[0] === dateStr);
 
    // 添加到结果数组中
    result.push({
        date: dateStr,
        count: count,
        data: dataContent
    });
}
 
// 根据星期一列降序排列结果数组
result.sort((a, b) => {
    return a.date > b.date ? -1 : 1;
});
 
// 将现有的 fillGrid 函数改为填充每一列的格子
function fillGrid(articles) {
    const gridContainer = document.getElementById('gridContainer');
    const gridItemTemplate = document.createElement('div');
    gridItemTemplate.className = 'grid-item';
 
    // 填充格子
    articles.slice().reverse().forEach((article, index) => {
        // 复制模板格子
        const gridItem = gridItemTemplate.cloneNode(false);
        gridItem.innerHTML = `<div class="word-count" data=${article.date}>${article.count}</div>`;
 
        // 确定格子位置,这里我们假设每列代表10天
        const colIndex = Math.floor(index / 7); // 计算列索引
        const rowIndex = index % 7; // 计算行索引
 
        // 将格子插入到正确的位置
        if (rowIndex === 0) {
            const gridColumn = document.createElement('div');
            gridColumn.className = 'grid-column';
            gridContainer.appendChild(gridColumn);
        }
        const gridColumns = document.getElementsByClassName('grid-column');
        gridColumns[colIndex].append(gridItem);
    });
}
 
fillGrid(result);

4o精简后的代码

function parseDate(str) {
    return new Date(str);
}
 
function getThisSunday(date) {
    const dayOfWeek = date.getDay();
    const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
    const thisSunday = new Date(date);
    thisSunday.setDate(thisSunday.getDate() + daysToSunday);
    return thisSunday;
}
 
const today = new Date('2024-05-17');
const sunday = getThisSunday(today);
let startDate = new Date(sunday);
startDate.setDate(sunday.getDate() - 62);
const result = [];
 
const dateCounts = {};
data.forEach(item => {
    const dateStr = parseDate(item.date).toISOString().split('T')[0];
    dateCounts[dateStr] = (dateCounts[dateStr] || 0) + 1;
});
 
for (let currentDate = sunday; currentDate >= startDate; currentDate.setDate(currentDate.getDate() - 1)) {
    const dateStr = currentDate.toISOString().split('T')[0];
    const count = dateCounts[dateStr] || 0;
    const dataContent = data.filter(item => parseDate(item.date).toISOString().split('T')[0] === dateStr);
 
    result.push({
        date: dateStr,
        count: count,
        data: dataContent
    });
}
 
function fillGrid(articles) {
    const gridContainer = document.getElementById('gridContainer');
    const gridItemTemplate = document.createElement('div');
    gridItemTemplate.className = 'grid-item';
 
    articles.slice().reverse().forEach((article, index) => {
        const gridItem = gridItemTemplate.cloneNode(false);
        gridItem.innerHTML = `<div class="word-count" data=${article.date}></div>`;
 
        const colIndex = Math.floor(index / 7);
        const rowIndex = index % 7;
 
        if (rowIndex === 0) {
            const gridColumn = document.createElement('div');
            gridColumn.className = 'grid-column';
            gridContainer.appendChild(gridColumn);
        }
        const gridColumns = document.getElementsByClassName('grid-column');
        gridColumns[colIndex].append(gridItem);
    });
}
 
fillGrid(result);